<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover"><title>JUC | SRS-Blog</title><meta name="author" content="SRS"><meta name="copyright" content="SRS"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="ffffff"><meta name="description" content="1. 线程池1.1 线程状态介绍当线程被创建并启动以后，它既不是一启动就进入了执行状态，也不是一直处于执行状态。线程对象在不同的时期有不同的状态。那么Java中的线程存在哪几种状态呢？Java中的线程 状态被定义在了java.lang.Thread.State枚举类中，State枚举类的源码如下： 12345678910111213141516171819202122232425262728293">
<meta property="og:type" content="article">
<meta property="og:title" content="JUC">
<meta property="og:url" content="https://srs-blog.github.io/2025/04/11/JUC/index.html">
<meta property="og:site_name" content="SRS-Blog">
<meta property="og:description" content="1. 线程池1.1 线程状态介绍当线程被创建并启动以后，它既不是一启动就进入了执行状态，也不是一直处于执行状态。线程对象在不同的时期有不同的状态。那么Java中的线程存在哪几种状态呢？Java中的线程 状态被定义在了java.lang.Thread.State枚举类中，State枚举类的源码如下： 12345678910111213141516171819202122232425262728293">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://srs-blog.github.io/img/bac-4.jpg">
<meta property="article:published_time" content="2025-04-10T16:00:00.000Z">
<meta property="article:modified_time" content="2025-04-10T16:00:00.000Z">
<meta property="article:author" content="SRS">
<meta property="article:tag" content="博客">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://srs-blog.github.io/img/bac-4.jpg"><script type="application/ld+json">{
  "@context": "https://schema.org",
  "@type": "BlogPosting",
  "headline": "JUC",
  "url": "https://srs-blog.github.io/2025/04/11/JUC/",
  "image": "https://srs-blog.github.io/img/bac-4.jpg",
  "datePublished": "2025-04-10T16:00:00.000Z",
  "dateModified": "2025-04-10T16:00:00.000Z",
  "author": [
    {
      "@type": "Person",
      "name": "SRS",
      "url": "https://srs-blog.github.io/"
    }
  ]
}</script><link rel="shortcut icon" href="/img/klld.png"><link rel="canonical" href="https://srs-blog.github.io/2025/04/11/JUC/index.html"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/node-snackbar/dist/snackbar.min.css" media="print" onload="this.media='all'"><script>
    (() => {
      
    const saveToLocal = {
      set: (key, value, ttl) => {
        if (!ttl) return
        const expiry = Date.now() + ttl * 86400000
        localStorage.setItem(key, JSON.stringify({ value, expiry }))
      },
      get: key => {
        const itemStr = localStorage.getItem(key)
        if (!itemStr) return undefined
        const { value, expiry } = JSON.parse(itemStr)
        if (Date.now() > expiry) {
          localStorage.removeItem(key)
          return undefined
        }
        return value
      }
    }

    window.btf = {
      saveToLocal,
      getScript: (url, attr = {}) => new Promise((resolve, reject) => {
        const script = document.createElement('script')
        script.src = url
        script.async = true
        Object.entries(attr).forEach(([key, val]) => script.setAttribute(key, val))
        script.onload = script.onreadystatechange = () => {
          if (!script.readyState || /loaded|complete/.test(script.readyState)) resolve()
        }
        script.onerror = reject
        document.head.appendChild(script)
      }),
      getCSS: (url, id) => new Promise((resolve, reject) => {
        const link = document.createElement('link')
        link.rel = 'stylesheet'
        link.href = url
        if (id) link.id = id
        link.onload = link.onreadystatechange = () => {
          if (!link.readyState || /loaded|complete/.test(link.readyState)) resolve()
        }
        link.onerror = reject
        document.head.appendChild(link)
      }),
      addGlobalFn: (key, fn, name = false, parent = window) => {
        if (!true && key.startsWith('pjax')) return
        const globalFn = parent.globalFn || {}
        globalFn[key] = globalFn[key] || {}
        globalFn[key][name || Object.keys(globalFn[key]).length] = fn
        parent.globalFn = globalFn
      }
    }
  
      
      const activateDarkMode = () => {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      const activateLightMode = () => {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', 'ffffff')
        }
      }

      btf.activateDarkMode = activateDarkMode
      btf.activateLightMode = activateLightMode

      const theme = saveToLocal.get('theme')
    
          const hour = new Date().getHours()
          const isNight = hour <= 6 || hour >= 18
          if (theme === undefined) isNight ? activateDarkMode() : activateLightMode()
          else theme === 'light' ? activateLightMode() : activateDarkMode()
        
      
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        document.documentElement.classList.toggle('hide-aside', asideStatus === 'hide')
      }
    
      
    const detectApple = () => {
      if (/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)) {
        document.documentElement.classList.add('apple')
      }
    }
    detectApple()
  
    })()
  </script><script>const GLOBAL_CONFIG = {
  root: '/',
  algolia: undefined,
  localSearch: {"path":"/search.xml","preload":false,"top_n_per_article":1,"unescape":false,"languages":{"hits_empty":"未找到符合您查询的内容：${query}","hits_stats":"共找到 ${hits} 篇文章"}},
  translate: {"defaultEncoding":2,"translateDelay":0,"msgToTraditionalChinese":"繁","msgToSimplifiedChinese":"简"},
  highlight: {"plugin":"highlight.js","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":230,"highlightFullpage":false,"highlightMacStyle":false},
  copy: {
    success: '复制成功',
    error: '复制失败',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: true,
    post: true
  },
  runtime: '',
  dateSuffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'null',
  Snackbar: {"chs_to_cht":"已切换为繁体中文","cht_to_chs":"已切换为简体中文","day_to_night":"关灯啦🌙，当前已成功切换至夜间模式！","night_to_day":"开灯啦🌞，当前已成功切换至白天模式！","bgLight":"#49b1f5","bgDark":"#1f1f1f","position":"top-right"},
  infinitegrid: {
    js: 'https://cdn.jsdelivr.net/npm/@egjs/infinitegrid/dist/infinitegrid.min.js',
    buttonText: '加载更多'
  },
  isPhotoFigcaption: false,
  islazyloadPlugin: true,
  isAnchor: false,
  percent: {
    toc: true,
    rightside: false,
  },
  autoDarkmode: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
  title: 'JUC',
  isHighlightShrink: false,
  isToc: true,
  pageType: 'post'
}</script><link rel="stylesheet" href="https://cdn1.tianli0.top/npm/element-ui@2.15.6/packages/theme-chalk/lib/index.css"><link rel="stylesheet" href="/css/custom.css"><link rel="stylesheet" href="/css/universe.css"><link rel="stylesheet" href="/css/emoji.css"><link rel="stylesheet" href="/css/progress_bar.css" media="defer" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/l-lin/font-awesome-animation/dist/font-awesome-animation.min.css"  media="defer" onload="this.media='all'"><link rel="stylesheet" href="/css/readPercent.css"><!-- hexo injector head_end start --><link rel="stylesheet" href="https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiperstyle.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://npm.elemecdn.com/hexo-butterfly-wowjs/lib/animate.min.css" media="print" onload="this.media='screen'"><link rel="stylesheet" href="https://npm.elemecdn.com/hexo-butterfly-tag-plugins-plus@latest/lib/assets/font-awesome-animation.min.css" media="defer" onload="this.media='all'"><link rel="stylesheet" href="https://npm.elemecdn.com/hexo-butterfly-tag-plugins-plus@latest/lib/tag_plugins.css" media="defer" onload="this.media='all'"><script src="https://npm.elemecdn.com/hexo-butterfly-tag-plugins-plus@latest/lib/assets/carousel-touch.js"></script><!-- hexo injector head_end end --><meta name="generator" content="Hexo 7.3.0"></head><body><div id="web_bg" style="background-image: url(/img/bac-5.png);"></div><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img text-center"><img src= "" data-lazy-src="/img/srs.jpg" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="site-data text-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">9</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">0</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">4</div></a></div><div class="menus_items"><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/"><i class="fa-fw icon-home"></i><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-home"></use></svg><span> 首页</span></a></div><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/archives/"><i class="fa-fw icon-shijianzhou"></i><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-shijianzhou"></use></svg><span> 时间轴</span></a></div><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/tags/"><i class="fa-fw icon-icon_pricetag"></i><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-icon_pricetag"></use></svg><span> 标签</span></a></div><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/categories/"><i class="fa-fw icon-shoukuanfenlei"></i><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-shoukuanfenlei"></use></svg><span> 分类</span></a></div><div class="menus_item"><a class="site-page group faa-parent animated-hover hide" href="javascript:void(0);"><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-liebiao"></use></svg><span> 休闲</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/bangumis/index.html"><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-shoukuanfenlei">                   </use></svg><span> 追番</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/music/"><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-yinle">                   </use></svg><span> 音乐</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/Gallery/"><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-zhaopian1">                   </use></svg><span> 照片</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/game/"><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-youxi">                   </use></svg><span> 游戏</span></a></li></ul></div><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/comments/"><i class="fa-fw icon-liuyanban"></i><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-liuyanban"></use></svg><span> 留言板</span></a></div><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/link/"><i class="fa-fw icon-youlian"></i><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-youlian"></use></svg><span> 友链</span></a></div><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/about/"><i class="fa-fw icon-aixin"></i><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-aixin"></use></svg><span> 关于</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url(/img/bac-4.jpg);"><nav id="nav"><span id="blog-info"><a href="/" title="SRS-Blog"><span class="site-name">SRS-Blog</span></a></span><div id="menus"><div class="menus_items"><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/"><i class="fa-fw icon-home"></i><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-home"></use></svg><span> 首页</span></a></div><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/archives/"><i class="fa-fw icon-shijianzhou"></i><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-shijianzhou"></use></svg><span> 时间轴</span></a></div><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/tags/"><i class="fa-fw icon-icon_pricetag"></i><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-icon_pricetag"></use></svg><span> 标签</span></a></div><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/categories/"><i class="fa-fw icon-shoukuanfenlei"></i><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-shoukuanfenlei"></use></svg><span> 分类</span></a></div><div class="menus_item"><a class="site-page group faa-parent animated-hover hide" href="javascript:void(0);"><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-liebiao"></use></svg><span> 休闲</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/bangumis/index.html"><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-shoukuanfenlei">                   </use></svg><span> 追番</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/music/"><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-yinle">                   </use></svg><span> 音乐</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/Gallery/"><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-zhaopian1">                   </use></svg><span> 照片</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/game/"><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-youxi">                   </use></svg><span> 游戏</span></a></li></ul></div><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/comments/"><i class="fa-fw icon-liuyanban"></i><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-liuyanban"></use></svg><span> 留言板</span></a></div><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/link/"><i class="fa-fw icon-youlian"></i><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-youlian"></use></svg><span> 友链</span></a></div><div class="menus_item"><a class="site-page faa-parent animated-hover" href="/about/"><i class="fa-fw icon-aixin"></i><svg class="icon faa-tada" aria-hidden="true"><use xlink:href="#icon-aixin"></use></svg><span> 关于</span></a></div></div><center id="name-container"><a id="page-name" href="javascript:scrollToTop()">PAGE_NAME</a></center><div id="nav-right"><a class="sun_moon faa-parent animated-hover" οnclick="switchNightMode()" title="日间和夜间模式切换" id="nightmode-button"><svg class="faa-tada" style="height:25px;width:25px;fill:currentColor;position:relative;top:7px" viewBox="0 0 1024 1024"><use id="modeicon" xlink:href="#icon-weather-color_moon-stars">       </use></svg></a><div id="toggle-menu"><a><i class="fas fa-bars fa-fw"></i></a></div></div></div></nav><div id="post-info"><h1 class="post-title">JUC</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2025-04-10T16:00:00.000Z" title="发表于 2025-04-11 00:00:00">2025-04-11</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2025-04-10T16:00:00.000Z" title="更新于 2025-04-11 00:00:00">2025-04-11</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/Java/">Java</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">总字数:</span><span class="word-count">11.3k</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>46分钟</span></span><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title=""><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">浏览量:</span><span id="busuanzi_value_page_pv"><i class="fa-solid fa-spinner fa-spin"></i></span></span></div></div></div><section class="main-hero-waves-area waves-area"><svg class="waves-svg" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" viewBox="0 24 150 28" preserveAspectRatio="none" shape-rendering="auto"><defs><path id="gentle-wave" d="M -160 44 c 30 0 58 -18 88 -18 s 58 18 88 18 s 58 -18 88 -18 s 58 18 88 18 v 44 h -352 Z"></path></defs><g class="parallax"><use href="#gentle-wave" x="48" y="0"></use><use href="#gentle-wave" x="48" y="3"></use><use href="#gentle-wave" x="48" y="5"></use><use href="#gentle-wave" x="48" y="7"></use></g></svg></section><div id="post-top-cover"><img class="nolazyload" id="post-top-bg" src= "" data-lazy-src="background-image: url(/img/bac-4.jpg);"></div></header><main class="layout" id="content-inner"><div id="post"><article class="container post-content" id="article-container"><div id="post-outdate-notice" data="{&quot;limitDay&quot;:365,&quot;messagePrev&quot;:&quot;It has been&quot;,&quot;messageNext&quot;:&quot;days since the last update, the content of the article may be outdated.&quot;,&quot;postUpdate&quot;:&quot;2025-04-11 00:00:00&quot;}" hidden></div><h2 id="1-线程池"><a href="#1-线程池" class="headerlink" title="1. 线程池"></a>1. 线程池</h2><h3 id="1-1-线程状态介绍"><a href="#1-1-线程状态介绍" class="headerlink" title="1.1 线程状态介绍"></a>1.1 线程状态介绍</h3><p>当线程被创建并启动以后，它既不是一启动就进入了执行状态，也不是一直处于执行状态。线程对象在不同的时期有不同的状态。那么Java中的线程存在哪几种状态呢？Java中的线程</p>
<p>状态被定义在了java.lang.Thread.State枚举类中，State枚举类的源码如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Thread</span> &#123;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">enum</span> <span class="title class_">State</span> &#123;</span><br><span class="line">    </span><br><span class="line">        <span class="comment">/* 新建 */</span></span><br><span class="line">        NEW , </span><br><span class="line"></span><br><span class="line">        <span class="comment">/* 可运行状态 */</span></span><br><span class="line">        RUNNABLE , </span><br><span class="line"></span><br><span class="line">        <span class="comment">/* 阻塞状态 */</span></span><br><span class="line">        BLOCKED , </span><br><span class="line"></span><br><span class="line">        <span class="comment">/* 无限等待状态 */</span></span><br><span class="line">        WAITING , </span><br><span class="line"></span><br><span class="line">        <span class="comment">/* 计时等待 */</span></span><br><span class="line">        TIMED_WAITING , </span><br><span class="line"></span><br><span class="line">        <span class="comment">/* 终止 */</span></span><br><span class="line">        TERMINATED;</span><br><span class="line">    </span><br><span class="line">	&#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 获取当前线程的状态</span></span><br><span class="line">    <span class="keyword">public</span> State <span class="title function_">getState</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> jdk.internal.misc.VM.toThreadState(threadStatus);</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>通过源码我们可以看到Java中的线程存在6种状态，每种线程状态的含义如下</p>
<div class="table-container">
<table>
<thead>
<tr>
<th>线程状态</th>
<th>具体含义</th>
</tr>
</thead>
<tbody>
<tr>
<td>NEW</td>
<td>一个尚未启动的线程的状态。也称之为初始状态、开始状态。线程刚被创建，但是并未启动。还没调用start方法。MyThread t = new MyThread()只有线程象，没有线程特征。</td>
</tr>
<tr>
<td>RUNNABLE</td>
<td>当我们调用线程对象的start方法，那么此时线程对象进入了RUNNABLE状态。那么此时才是真正的在JVM进程中创建了一个线程，线程一经启动并不是立即得到执行，线程的运行与否要听令与CPU的调度，那么我们把这个中间状态称之为可执行状态(RUNNABLE)也就是说它具备执行的资格，但是并没有真正的执行起来而是在等待CPU的度。</td>
</tr>
<tr>
<td>BLOCKED</td>
<td>当一个线程试图获取一个对象锁，而该对象锁被其他的线程持有，则该线程进入Blocked状态；当该线程持有锁时，该线程将变成Runnable状态。</td>
</tr>
<tr>
<td>WAITING</td>
<td>一个正在等待的线程的状态。也称之为等待状态。造成线程等待的原因有两种，分别是调用Object.wait()、join()方法。处于等待状态的线程，正在等待其他线程去执行一个特定的操作。例如：因为wait()而等待的线程正在等待另一个线程去调用notify()或notifyAll()；一个因为join()而等待的线程正在等待另一个线程结束。</td>
</tr>
<tr>
<td>TIMED_WAITING</td>
<td>一个在限定时间内等待的线程的状态。也称之为限时等待状态。造成线程限时等待状态的原因有三种，分别是：Thread.sleep(long)，Object.wait(long)、join(long)。</td>
</tr>
<tr>
<td>TERMINATED</td>
<td>一个完全运行完成的线程的状态。也称之为终止状态、结束状态</td>
</tr>
</tbody>
</table>
</div>
<p>各个状态的转换，如下图所示：</p>
<p><img src= "" data-lazy-src="/img/1591163781941.png" alt="1591163781941"></p>
<h3 id="1-2-线程池-基本原理"><a href="#1-2-线程池-基本原理" class="headerlink" title="1.2 线程池-基本原理"></a>1.2 线程池-基本原理</h3><p><strong>概述 :</strong> </p>
<p>​    提到池，大家应该能想到的就是水池。水池就是一个容器，在该容器中存储了很多的水。那么什么是线程池呢？线程池也是可以看做成一个池子，在该池子中存储很多个线程。</p>
<p>线程池存在的意义：</p>
<p>​    系统创建一个线程的成本是比较高的，因为它涉及到与操作系统交互，当程序中需要创建大量生存期很短暂的线程时，频繁的创建和销毁线程对系统的资源消耗有可能大于业务处理是对系</p>
<p>​    统资源的消耗，这样就有点”舍本逐末”了。针对这一种情况，为了提高性能，我们就可以采用线程池。线程池在启动的时，会创建大量空闲线程，当我们向线程池提交任务的时，线程池就</p>
<p>​    会启动一个线程来执行该任务。等待任务执行完毕以后，线程并不会死亡，而是再次返回到线程池中称为空闲状态。等待下一次任务的执行。</p>
<p><strong>线程池的设计思路 :</strong></p>
<ol>
<li>准备一个任务容器</li>
<li>一次性启动多个(2个)消费者线程</li>
<li>刚开始任务容器是空的，所以线程都在wait</li>
<li>直到一个外部线程向这个任务容器中扔了一个”任务”，就会有一个消费者线程被唤醒</li>
<li>这个消费者线程取出”任务”，并且执行这个任务，执行完毕后，继续等待下一次任务的到来</li>
</ol>
<h3 id="1-3-线程池-Executors默认线程池"><a href="#1-3-线程池-Executors默认线程池" class="headerlink" title="1.3 线程池-Executors默认线程池"></a>1.3 线程池-Executors默认线程池</h3><p>概述 : JDK对线程池也进行了相关的实现，在真实企业开发中我们也很少去自定义线程池，而是使用JDK中自带的线程池。</p>
<p>我们可以使用Executors中所提供的<strong>静态</strong>方法来创建线程池</p>
<p>​    static ExecutorService newCachedThreadPool()   创建一个默认的线程池<br>    static newFixedThreadPool(int nThreads)        创建一个指定最多线程数量的线程池</p>
<p><strong>代码实现 :</strong> </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.mythreadpool;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//static ExecutorService newCachedThreadPool()   创建一个默认的线程池</span></span><br><span class="line"><span class="comment">//static newFixedThreadPool(int nThreads)	    创建一个指定最多线程数量的线程池</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.ExecutorService;</span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.Executors;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyThreadPoolDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//1,创建一个默认的线程池对象.池子中默认是空的.默认最多可以容纳int类型的最大值.</span></span><br><span class="line">        <span class="type">ExecutorService</span> <span class="variable">executorService</span> <span class="operator">=</span> Executors.newCachedThreadPool();</span><br><span class="line">        <span class="comment">//Executors --- 可以帮助我们创建线程池对象</span></span><br><span class="line">        <span class="comment">//ExecutorService --- 可以帮助我们控制线程池</span></span><br><span class="line"></span><br><span class="line">        executorService.submit(()-&gt;&#123;</span><br><span class="line">            System.out.println(Thread.currentThread().getName() + <span class="string">&quot;在执行了&quot;</span>);</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//Thread.sleep(2000);</span></span><br><span class="line"></span><br><span class="line">        executorService.submit(()-&gt;&#123;</span><br><span class="line">            System.out.println(Thread.currentThread().getName() + <span class="string">&quot;在执行了&quot;</span>);</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line">        executorService.shutdown();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h3 id="1-4-线程池-Executors创建指定上限的线程池"><a href="#1-4-线程池-Executors创建指定上限的线程池" class="headerlink" title="1.4 线程池-Executors创建指定上限的线程池"></a>1.4 线程池-Executors创建指定上限的线程池</h3><p><strong>使用Executors中所提供的静态方法来创建线程池</strong></p>
<p>​    static ExecutorService newFixedThreadPool(int nThreads) : 创建一个指定最多线程数量的线程池</p>
<p><strong>代码实现 :</strong> </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.mythreadpool;</span><br><span class="line"></span><br><span class="line"><span class="comment">//static ExecutorService newFixedThreadPool(int nThreads)</span></span><br><span class="line"><span class="comment">//创建一个指定最多线程数量的线程池</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.ExecutorService;</span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.Executors;</span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.ThreadPoolExecutor;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyThreadPoolDemo2</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">//参数不是初始值而是最大值</span></span><br><span class="line">        <span class="type">ExecutorService</span> <span class="variable">executorService</span> <span class="operator">=</span> Executors.newFixedThreadPool(<span class="number">10</span>);</span><br><span class="line"></span><br><span class="line">        <span class="type">ThreadPoolExecutor</span> <span class="variable">pool</span> <span class="operator">=</span> (ThreadPoolExecutor) executorService;</span><br><span class="line">        System.out.println(pool.getPoolSize());<span class="comment">//0</span></span><br><span class="line"></span><br><span class="line">        executorService.submit(()-&gt;&#123;</span><br><span class="line">            System.out.println(Thread.currentThread().getName() + <span class="string">&quot;在执行了&quot;</span>);</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line">        executorService.submit(()-&gt;&#123;</span><br><span class="line">            System.out.println(Thread.currentThread().getName() + <span class="string">&quot;在执行了&quot;</span>);</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line">        System.out.println(pool.getPoolSize());<span class="comment">//2</span></span><br><span class="line"><span class="comment">//        executorService.shutdown();</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h3 id="1-5-自定义线程池-ThreadPoolExecutor"><a href="#1-5-自定义线程池-ThreadPoolExecutor" class="headerlink" title="1.5 自定义线程池-ThreadPoolExecutor"></a>1.5 自定义线程池-ThreadPoolExecutor</h3><p><strong>创建线程池对象 :</strong> </p>
<p>ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(核心线程数量,最大线程数量,空闲线程最大存活时间,时间单位,任务队列,创建线程工厂,任务的拒绝策略);</p>
<p><strong>代码实现 :</strong> </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.mythreadpool;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.ArrayBlockingQueue;</span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.Executors;</span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.ThreadPoolExecutor;</span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.TimeUnit;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyThreadPoolDemo3</span> &#123;</span><br><span class="line"><span class="comment">//    参数一：核心线程数量</span></span><br><span class="line"><span class="comment">//    参数二：最大线程数</span></span><br><span class="line"><span class="comment">//    参数三：空闲线程最大存活时间</span></span><br><span class="line"><span class="comment">//    参数四：时间单位</span></span><br><span class="line"><span class="comment">//    参数五：任务队列</span></span><br><span class="line"><span class="comment">//    参数六：创建线程工厂</span></span><br><span class="line"><span class="comment">//    参数七：任务的拒绝策略</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">ThreadPoolExecutor</span> <span class="variable">pool</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ThreadPoolExecutor</span>(<span class="number">2</span>,<span class="number">5</span>,<span class="number">2</span>,TimeUnit.SECONDS,<span class="keyword">new</span> <span class="title class_">ArrayBlockingQueue</span>&lt;&gt;(<span class="number">10</span>), Executors.defaultThreadFactory(),<span class="keyword">new</span> <span class="title class_">ThreadPoolExecutor</span>.AbortPolicy());</span><br><span class="line">        pool.submit(<span class="keyword">new</span> <span class="title class_">MyRunnable</span>());</span><br><span class="line">        pool.submit(<span class="keyword">new</span> <span class="title class_">MyRunnable</span>());</span><br><span class="line"></span><br><span class="line">        pool.shutdown();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="1-6-线程池-参数详解"><a href="#1-6-线程池-参数详解" class="headerlink" title="1.6 线程池-参数详解"></a>1.6 线程池-参数详解</h3><p><img src= "" data-lazy-src="/img/1591165506516.png" alt="1591165506516"></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="title function_">ThreadPoolExecutor</span><span class="params">(<span class="type">int</span> corePoolSize,</span></span><br><span class="line"><span class="params">                              <span class="type">int</span> maximumPoolSize,</span></span><br><span class="line"><span class="params">                              <span class="type">long</span> keepAliveTime,</span></span><br><span class="line"><span class="params">                              TimeUnit unit,</span></span><br><span class="line"><span class="params">                              BlockingQueue&lt;Runnable&gt; workQueue,</span></span><br><span class="line"><span class="params">                              ThreadFactory threadFactory,</span></span><br><span class="line"><span class="params">                              RejectedExecutionHandler handler)</span></span><br><span class="line">    </span><br><span class="line">corePoolSize：   核心线程的最大值，不能小于<span class="number">0</span></span><br><span class="line">maximumPoolSize：最大线程数，不能小于等于<span class="number">0</span>，maximumPoolSize &gt;= corePoolSize</span><br><span class="line">keepAliveTime：  空闲线程最大存活时间,不能小于<span class="number">0</span></span><br><span class="line">unit：           时间单位</span><br><span class="line">workQueue：      任务队列，不能为<span class="literal">null</span></span><br><span class="line">threadFactory：  创建线程工厂,不能为<span class="literal">null</span>      </span><br><span class="line">handler：        任务的拒绝策略,不能为<span class="literal">null</span>  </span><br></pre></td></tr></table></figure>
<h3 id="1-7-线程池-非默认任务拒绝策略"><a href="#1-7-线程池-非默认任务拒绝策略" class="headerlink" title="1.7 线程池-非默认任务拒绝策略"></a>1.7 线程池-非默认任务拒绝策略</h3><p>RejectedExecutionHandler是jdk提供的一个任务拒绝策略接口，它下面存在4个子类。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">ThreadPoolExecutor.AbortPolicy: 		    丢弃任务并抛出RejectedExecutionException异常。是默认的策略。</span><br><span class="line">ThreadPoolExecutor.DiscardPolicy： 		   丢弃任务，但是不抛出异常 这是不推荐的做法。</span><br><span class="line">ThreadPoolExecutor.DiscardOldestPolicy：    抛弃队列中等待最久的任务 然后把当前任务加入队列中。</span><br><span class="line">ThreadPoolExecutor.CallerRunsPolicy:        调用任务的run()方法绕过线程池直接执行。</span><br></pre></td></tr></table></figure>
<p>注：明确线程池对多可执行的任务数 = 队列容量 + 最大线程数</p>
<p><strong>案例演示1</strong>：演示ThreadPoolExecutor.AbortPolicy任务处理策略</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ThreadPoolExecutorDemo01</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line"></span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 核心线程数量为1 ， 最大线程池数量为3, 任务容器的容量为1 ,空闲线程的最大存在时间为20s</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="type">ThreadPoolExecutor</span> <span class="variable">threadPoolExecutor</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ThreadPoolExecutor</span>(<span class="number">1</span> , <span class="number">3</span> , <span class="number">20</span> , TimeUnit.SECONDS ,</span><br><span class="line">                <span class="keyword">new</span> <span class="title class_">ArrayBlockingQueue</span>&lt;&gt;(<span class="number">1</span>) , Executors.defaultThreadFactory() , <span class="keyword">new</span> <span class="title class_">ThreadPoolExecutor</span>.AbortPolicy()) ;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 提交5个任务，而该线程池最多可以处理4个任务，当我们使用AbortPolicy这个任务处理策略的时候，就会抛出异常</span></span><br><span class="line">        <span class="keyword">for</span>(<span class="type">int</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">0</span> ; x &lt; <span class="number">5</span> ; x++) &#123;</span><br><span class="line">            threadPoolExecutor.submit(() -&gt; &#123;</span><br><span class="line">                System.out.println(Thread.currentThread().getName() + <span class="string">&quot;----&gt;&gt; 执行了任务&quot;</span>);</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>控制台输出结果</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">pool-<span class="number">1</span>-thread-<span class="number">1</span>----&gt;&gt; 执行了任务</span><br><span class="line">pool-<span class="number">1</span>-thread-<span class="number">3</span>----&gt;&gt; 执行了任务</span><br><span class="line">pool-<span class="number">1</span>-thread-<span class="number">2</span>----&gt;&gt; 执行了任务</span><br><span class="line">pool-<span class="number">1</span>-thread-<span class="number">3</span>----&gt;&gt; 执行了任务</span><br></pre></td></tr></table></figure>
<p>控制台报错，仅仅执行了4个任务，有一个任务被丢弃了</p>
<p><strong>案例演示2</strong>：演示ThreadPoolExecutor.DiscardPolicy任务处理策略</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ThreadPoolExecutorDemo02</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 核心线程数量为1 ， 最大线程池数量为3, 任务容器的容量为1 ,空闲线程的最大存在时间为20s</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="type">ThreadPoolExecutor</span> <span class="variable">threadPoolExecutor</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ThreadPoolExecutor</span>(<span class="number">1</span> , <span class="number">3</span> , <span class="number">20</span> , TimeUnit.SECONDS ,</span><br><span class="line">                <span class="keyword">new</span> <span class="title class_">ArrayBlockingQueue</span>&lt;&gt;(<span class="number">1</span>) , Executors.defaultThreadFactory() , <span class="keyword">new</span> <span class="title class_">ThreadPoolExecutor</span>.DiscardPolicy()) ;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 提交5个任务，而该线程池最多可以处理4个任务，当我们使用DiscardPolicy这个任务处理策略的时候，控制台不会报错</span></span><br><span class="line">        <span class="keyword">for</span>(<span class="type">int</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">0</span> ; x &lt; <span class="number">5</span> ; x++) &#123;</span><br><span class="line">            threadPoolExecutor.submit(() -&gt; &#123;</span><br><span class="line">                System.out.println(Thread.currentThread().getName() + <span class="string">&quot;----&gt;&gt; 执行了任务&quot;</span>);</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>控制台输出结果</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">pool-<span class="number">1</span>-thread-<span class="number">1</span>----&gt;&gt; 执行了任务</span><br><span class="line">pool-<span class="number">1</span>-thread-<span class="number">1</span>----&gt;&gt; 执行了任务</span><br><span class="line">pool-<span class="number">1</span>-thread-<span class="number">3</span>----&gt;&gt; 执行了任务</span><br><span class="line">pool-<span class="number">1</span>-thread-<span class="number">2</span>----&gt;&gt; 执行了任务</span><br></pre></td></tr></table></figure>
<p>控制台没有报错，仅仅执行了4个任务，有一个任务被丢弃了</p>
<p><strong>案例演示3</strong>：演示ThreadPoolExecutor.DiscardOldestPolicy任务处理策略</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ThreadPoolExecutorDemo02</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 核心线程数量为1 ， 最大线程池数量为3, 任务容器的容量为1 ,空闲线程的最大存在时间为20s</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        ThreadPoolExecutor threadPoolExecutor;</span><br><span class="line">        threadPoolExecutor = <span class="keyword">new</span> <span class="title class_">ThreadPoolExecutor</span>(<span class="number">1</span> , <span class="number">3</span> , <span class="number">20</span> , TimeUnit.SECONDS ,</span><br><span class="line">                <span class="keyword">new</span> <span class="title class_">ArrayBlockingQueue</span>&lt;&gt;(<span class="number">1</span>) , Executors.defaultThreadFactory() , <span class="keyword">new</span> <span class="title class_">ThreadPoolExecutor</span>.DiscardOldestPolicy());</span><br><span class="line">        <span class="comment">// 提交5个任务</span></span><br><span class="line">        <span class="keyword">for</span>(<span class="type">int</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">0</span> ; x &lt; <span class="number">5</span> ; x++) &#123;</span><br><span class="line">            <span class="comment">// 定义一个变量，来指定指定当前执行的任务;这个变量需要被final修饰</span></span><br><span class="line">            <span class="keyword">final</span> <span class="type">int</span> <span class="variable">y</span> <span class="operator">=</span> x ;</span><br><span class="line">            threadPoolExecutor.submit(() -&gt; &#123;</span><br><span class="line">                System.out.println(Thread.currentThread().getName() + <span class="string">&quot;----&gt;&gt; 执行了任务&quot;</span> + y);</span><br><span class="line">            &#125;);     </span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>控制台输出结果</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">pool-<span class="number">1</span>-thread-<span class="number">2</span>----&gt;&gt; 执行了任务<span class="number">2</span></span><br><span class="line">pool-<span class="number">1</span>-thread-<span class="number">1</span>----&gt;&gt; 执行了任务<span class="number">0</span></span><br><span class="line">pool-<span class="number">1</span>-thread-<span class="number">3</span>----&gt;&gt; 执行了任务<span class="number">3</span></span><br><span class="line">pool-<span class="number">1</span>-thread-<span class="number">1</span>----&gt;&gt; 执行了任务<span class="number">4</span></span><br></pre></td></tr></table></figure>
<p>由于任务1在线程池中等待时间最长，因此任务1被丢弃。</p>
<p><strong>案例演示4</strong>：演示ThreadPoolExecutor.CallerRunsPolicy任务处理策略</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ThreadPoolExecutorDemo04</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line"></span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 核心线程数量为1 ， 最大线程池数量为3, 任务容器的容量为1 ,空闲线程的最大存在时间为20s</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        ThreadPoolExecutor threadPoolExecutor;</span><br><span class="line">        threadPoolExecutor = <span class="keyword">new</span> <span class="title class_">ThreadPoolExecutor</span>(<span class="number">1</span> , <span class="number">3</span> , <span class="number">20</span> , TimeUnit.SECONDS ,</span><br><span class="line">                <span class="keyword">new</span> <span class="title class_">ArrayBlockingQueue</span>&lt;&gt;(<span class="number">1</span>) , Executors.defaultThreadFactory() , <span class="keyword">new</span> <span class="title class_">ThreadPoolExecutor</span>.CallerRunsPolicy());</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 提交5个任务</span></span><br><span class="line">        <span class="keyword">for</span>(<span class="type">int</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">0</span> ; x &lt; <span class="number">5</span> ; x++) &#123;</span><br><span class="line">            threadPoolExecutor.submit(() -&gt; &#123;</span><br><span class="line">                System.out.println(Thread.currentThread().getName() + <span class="string">&quot;----&gt;&gt; 执行了任务&quot;</span>);</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>控制台输出结果</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">pool-<span class="number">1</span>-thread-<span class="number">1</span>----&gt;&gt; 执行了任务</span><br><span class="line">pool-<span class="number">1</span>-thread-<span class="number">3</span>----&gt;&gt; 执行了任务</span><br><span class="line">pool-<span class="number">1</span>-thread-<span class="number">2</span>----&gt;&gt; 执行了任务</span><br><span class="line">pool-<span class="number">1</span>-thread-<span class="number">1</span>----&gt;&gt; 执行了任务</span><br><span class="line">main----&gt;&gt; 执行了任务</span><br></pre></td></tr></table></figure>
<p>通过控制台的输出，我们可以看到次策略没有通过线程池中的线程执行任务，而是直接调用任务的run()方法绕过线程池直接执行。</p>
<h3 id="1-8-线程池需要多大"><a href="#1-8-线程池需要多大" class="headerlink" title="1.8 线程池需要多大"></a>1.8 线程池需要多大</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//获取最大并行数</span></span><br><span class="line"><span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> Runtime.getRuntime().availableProcessors();</span><br><span class="line">System.out.println(i);</span><br></pre></td></tr></table></figure>
<p>判断是cpu密集型（计算多）还是IO密集型（数据库操作多），分别计算线程池大小，cpu计算时间和等待时间可以通过<strong>thread dump</strong>工具测试</p>
<p><img src= "" data-lazy-src="C:\Users\Lenovo\AppData\Local\Temp\1739933031737.png" alt="73993303173"></p>
<h2 id="2-多线程综合练习"><a href="#2-多线程综合练习" class="headerlink" title="2. 多线程综合练习"></a>2. 多线程综合练习</h2><h3 id="练习一：售票"><a href="#练习一：售票" class="headerlink" title="练习一：售票"></a>练习一：售票</h3><p>需求：</p>
<p>​    一共有1000张电影票,可以在两个窗口领取,假设每次领取的时间为3000毫秒,</p>
<p>​    请用多线程模拟卖票过程并打印剩余电影票的数量</p>
<p>代码示例：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyThread</span> <span class="keyword">extends</span> <span class="title class_">Thread</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//第一种方式实现多线程，测试类中MyThread会创建多次，所以需要加static</span></span><br><span class="line">    <span class="keyword">static</span> <span class="type">int</span> <span class="variable">ticket</span> <span class="operator">=</span> <span class="number">1000</span>;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">//1.循环</span></span><br><span class="line">        <span class="keyword">while</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">            <span class="comment">//2.同步代码块</span></span><br><span class="line">            <span class="keyword">synchronized</span> (MyThread.class) &#123;</span><br><span class="line">                <span class="comment">//3.判断共享数据（已经到末尾）</span></span><br><span class="line">                <span class="keyword">if</span> (ticket == <span class="number">0</span>) &#123;</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="comment">//4.判断共享数据（没有到末尾）</span></span><br><span class="line">                    <span class="keyword">try</span> &#123;</span><br><span class="line">                        Thread.sleep(<span class="number">3000</span>);</span><br><span class="line">                    &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                        e.printStackTrace();</span><br><span class="line">                    &#125;</span><br><span class="line">                    ticket--;</span><br><span class="line">                    System.out.println(getName() + <span class="string">&quot;在卖票，还剩下&quot;</span> + ticket + <span class="string">&quot;张票!!!&quot;</span>);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Test</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">       <span class="comment">/*</span></span><br><span class="line"><span class="comment">            一共有1000张电影票,可以在两个窗口领取,假设每次领取的时间为3000毫秒,</span></span><br><span class="line"><span class="comment">            要求:请用多线程模拟卖票过程并打印剩余电影票的数量</span></span><br><span class="line"><span class="comment">        */</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">//创建线程对象</span></span><br><span class="line">        <span class="type">MyThread</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread</span>();</span><br><span class="line">        <span class="type">MyThread</span> <span class="variable">t2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread</span>();</span><br><span class="line"></span><br><span class="line">        <span class="comment">//给线程设置名字</span></span><br><span class="line">        t1.setName(<span class="string">&quot;窗口1&quot;</span>);</span><br><span class="line">        t2.setName(<span class="string">&quot;窗口2&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//开启线程</span></span><br><span class="line">        t1.start();</span><br><span class="line">        t2.start();</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h3 id="练习二：赠送礼物"><a href="#练习二：赠送礼物" class="headerlink" title="练习二：赠送礼物"></a>练习二：赠送礼物</h3><p>需求：</p>
<p>​    有100份礼品,两人同时发送，当剩下的礼品小于10份的时候则不再送出。</p>
<p>​    利用多线程模拟该过程并将线程的名字和礼物的剩余数量打印出来.</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyRunable</span> <span class="keyword">implements</span> <span class="title class_">Runnable</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//第二种方式实现多线程，测试类中MyRunable只创建一次，所以不需要加static</span></span><br><span class="line">    <span class="type">int</span> <span class="variable">count</span> <span class="operator">=</span> <span class="number">100</span>;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">//1.循环</span></span><br><span class="line">        <span class="keyword">while</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">            <span class="comment">//2.同步代码块</span></span><br><span class="line">            <span class="keyword">synchronized</span> (MyThread.class) &#123;</span><br><span class="line">                <span class="comment">//3.判断共享数据（已经到末尾）</span></span><br><span class="line">                <span class="keyword">if</span> (count &lt; <span class="number">10</span>) &#123;</span><br><span class="line">                    System.out.println(<span class="string">&quot;礼物还剩下&quot;</span> + count + <span class="string">&quot;不再赠送&quot;</span>);</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="comment">//4.判断共享数据（没有到末尾）</span></span><br><span class="line">                    count--;</span><br><span class="line">                    System.out.println(Thread.currentThread().getName() + <span class="string">&quot;在赠送礼物，还剩下&quot;</span> + count + <span class="string">&quot;个礼物!!!&quot;</span>);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Test</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">/*</span></span><br><span class="line"><span class="comment">            有100份礼品,两人同时发送，当剩下的礼品小于10份的时候则不再送出，</span></span><br><span class="line"><span class="comment">            利用多线程模拟该过程并将线程的名字和礼物的剩余数量打印出来.</span></span><br><span class="line"><span class="comment">        */</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">//创建参数对象</span></span><br><span class="line">        <span class="type">MyRunable</span> <span class="variable">mr</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyRunable</span>();</span><br><span class="line"></span><br><span class="line">        <span class="comment">//创建线程对象</span></span><br><span class="line">        <span class="type">Thread</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(mr,<span class="string">&quot;窗口1&quot;</span>);</span><br><span class="line">        <span class="type">Thread</span> <span class="variable">t2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(mr,<span class="string">&quot;窗口2&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//启动线程</span></span><br><span class="line">        t1.start();</span><br><span class="line">        t2.start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h3 id="练习三：打印数字"><a href="#练习三：打印数字" class="headerlink" title="练习三：打印数字"></a>练习三：打印数字</h3><p>需求：</p>
<p>​    同时开启两个线程，共同获取1-100之间的所有数字。</p>
<p>​    将输出所有的奇数。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyRunable</span> <span class="keyword">implements</span> <span class="title class_">Runnable</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//第二种方式实现多线程，测试类中MyRunable只创建一次，所以不需要加static</span></span><br><span class="line">    <span class="type">int</span> <span class="variable">number</span> <span class="operator">=</span> <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">//1.循环</span></span><br><span class="line">        <span class="keyword">while</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">            <span class="comment">//2.同步代码块</span></span><br><span class="line">            <span class="keyword">synchronized</span> (MyThread.class) &#123;</span><br><span class="line">                <span class="comment">//3.判断共享数据（已经到末尾）</span></span><br><span class="line">                <span class="keyword">if</span> (number &gt; <span class="number">100</span>) &#123;</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="comment">//4.判断共享数据（没有到末尾）</span></span><br><span class="line">                    <span class="keyword">if</span>(number % <span class="number">2</span> == <span class="number">1</span>)&#123;</span><br><span class="line">                        System.out.println(Thread.currentThread().getName() + <span class="string">&quot;打印数字&quot;</span> + number);</span><br><span class="line">                    &#125;</span><br><span class="line">                    number++;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Test</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">/*</span></span><br><span class="line"><span class="comment">           同时开启两个线程，共同获取1-100之间的所有数字。</span></span><br><span class="line"><span class="comment">           要求：将输出所有的奇数。</span></span><br><span class="line"><span class="comment">        */</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="comment">//创建参数对象</span></span><br><span class="line">        <span class="type">MyRunable</span> <span class="variable">mr</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyRunable</span>();</span><br><span class="line"></span><br><span class="line">        <span class="comment">//创建线程对象</span></span><br><span class="line">        <span class="type">Thread</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(mr,<span class="string">&quot;线程A&quot;</span>);</span><br><span class="line">        <span class="type">Thread</span> <span class="variable">t2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(mr,<span class="string">&quot;线程B&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//启动线程</span></span><br><span class="line">        t1.start();</span><br><span class="line">        t2.start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="练习四：抢红包"><a href="#练习四：抢红包" class="headerlink" title="练习四：抢红包"></a>练习四：抢红包</h3><p>需求：</p>
<p>​    抢红包也用到了多线程。</p>
<p>​    假设：100块，分成了3个包，现在有5个人去抢。</p>
<p>​    其中，红包是共享数据。</p>
<p>​    5个人是5条线程。</p>
<p>​    打印结果如下：</p>
<p>​          XXX抢到了XXX元</p>
<p>​          XXX抢到了XXX元</p>
<pre><code>      XXX抢到了XXX元

      XXX没抢到

      XXX没抢到
</code></pre><p>解决方案一：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyThread</span> <span class="keyword">extends</span> <span class="title class_">Thread</span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//共享数据</span></span><br><span class="line">    <span class="comment">//100块，分成了3个包</span></span><br><span class="line">    <span class="keyword">static</span> <span class="type">double</span> <span class="variable">money</span> <span class="operator">=</span> <span class="number">100</span>;</span><br><span class="line">    <span class="keyword">static</span> <span class="type">int</span> <span class="variable">count</span> <span class="operator">=</span> <span class="number">3</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//最小的中奖金额</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">double</span> <span class="variable">MIN</span> <span class="operator">=</span> <span class="number">0.01</span>;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">//同步代码块</span></span><br><span class="line">        <span class="keyword">synchronized</span> (MyThread.class)&#123;</span><br><span class="line">            <span class="keyword">if</span>(count == <span class="number">0</span>)&#123;</span><br><span class="line">                <span class="comment">//判断，共享数据是否到了末尾（已经到末尾）</span></span><br><span class="line">                System.out.println(getName() + <span class="string">&quot;没有抢到红包！&quot;</span>);</span><br><span class="line">            &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                <span class="comment">//判断，共享数据是否到了末尾（没有到末尾）</span></span><br><span class="line">                <span class="comment">//定义一个变量，表示中奖的金额</span></span><br><span class="line">                <span class="type">double</span> <span class="variable">prize</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">                <span class="keyword">if</span>(count == <span class="number">1</span>)&#123;</span><br><span class="line">                    <span class="comment">//表示此时是最后一个红包</span></span><br><span class="line">                    <span class="comment">//就无需随机，剩余所有的钱都是中奖金额</span></span><br><span class="line">                    prize = money;</span><br><span class="line">                &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                    <span class="comment">//表示第一次，第二次（随机）</span></span><br><span class="line">                    <span class="type">Random</span> <span class="variable">r</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Random</span>();</span><br><span class="line">                    <span class="comment">//100 元   3个包</span></span><br><span class="line">                    <span class="comment">//第一个红包：99.98</span></span><br><span class="line">                    <span class="comment">//100 - (3-1) * 0.01</span></span><br><span class="line">                    <span class="type">double</span> <span class="variable">bounds</span> <span class="operator">=</span> money - (count - <span class="number">1</span>) * MIN;</span><br><span class="line">                    prize = r.nextDouble(bounds);</span><br><span class="line">                    <span class="keyword">if</span>(prize &lt; MIN)&#123;</span><br><span class="line">                        prize = MIN;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="comment">//从money当中，去掉当前中奖的金额</span></span><br><span class="line">                money = money - prize;</span><br><span class="line">                <span class="comment">//红包的个数-1</span></span><br><span class="line">                count--;</span><br><span class="line">                <span class="comment">//本次红包的信息进行打印</span></span><br><span class="line">                System.out.println(getName() + <span class="string">&quot;抢到了&quot;</span> + prize + <span class="string">&quot;元&quot;</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Test</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">/*</span></span><br><span class="line"><span class="comment">            微信中的抢红包也用到了多线程。</span></span><br><span class="line"><span class="comment">            假设：100块，分成了3个包，现在有5个人去抢。</span></span><br><span class="line"><span class="comment">            其中，红包是共享数据。</span></span><br><span class="line"><span class="comment">            5个人是5条线程。</span></span><br><span class="line"><span class="comment">            打印结果如下：</span></span><br><span class="line"><span class="comment">            	XXX抢到了XXX元</span></span><br><span class="line"><span class="comment">            	XXX抢到了XXX元</span></span><br><span class="line"><span class="comment">            	XXX抢到了XXX元</span></span><br><span class="line"><span class="comment">            	XXX没抢到</span></span><br><span class="line"><span class="comment">            	XXX没抢到</span></span><br><span class="line"><span class="comment">        */</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">//创建线程的对象</span></span><br><span class="line">        <span class="type">MyThread</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread</span>();</span><br><span class="line">        <span class="type">MyThread</span> <span class="variable">t2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread</span>();</span><br><span class="line">        <span class="type">MyThread</span> <span class="variable">t3</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread</span>();</span><br><span class="line">        <span class="type">MyThread</span> <span class="variable">t4</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread</span>();</span><br><span class="line">        <span class="type">MyThread</span> <span class="variable">t5</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread</span>();</span><br><span class="line"></span><br><span class="line">        <span class="comment">//给线程设置名字</span></span><br><span class="line">        t1.setName(<span class="string">&quot;小A&quot;</span>);</span><br><span class="line">        t2.setName(<span class="string">&quot;小QQ&quot;</span>);</span><br><span class="line">        t3.setName(<span class="string">&quot;小哈哈&quot;</span>);</span><br><span class="line">        t4.setName(<span class="string">&quot;小诗诗&quot;</span>);</span><br><span class="line">        t5.setName(<span class="string">&quot;小丹丹&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//启动线程</span></span><br><span class="line">        t1.start();</span><br><span class="line">        t2.start();</span><br><span class="line">        t3.start();</span><br><span class="line">        t4.start();</span><br><span class="line">        t5.start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>解决方案二：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyThread</span> <span class="keyword">extends</span> <span class="title class_">Thread</span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//总金额</span></span><br><span class="line">    <span class="keyword">static</span> <span class="type">BigDecimal</span> <span class="variable">money</span> <span class="operator">=</span> BigDecimal.valueOf(<span class="number">100.0</span>);</span><br><span class="line">    <span class="comment">//个数</span></span><br><span class="line">    <span class="keyword">static</span> <span class="type">int</span> <span class="variable">count</span> <span class="operator">=</span> <span class="number">3</span>;</span><br><span class="line">    <span class="comment">//最小抽奖金额</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">BigDecimal</span> <span class="variable">MIN</span> <span class="operator">=</span> BigDecimal.valueOf(<span class="number">0.01</span>);</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">synchronized</span> (MyThread.class)&#123;</span><br><span class="line">            <span class="keyword">if</span>(count == <span class="number">0</span>)&#123;</span><br><span class="line">                System.out.println(getName() + <span class="string">&quot;没有抢到红包！&quot;</span>);</span><br><span class="line">            &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                <span class="comment">//中奖金额</span></span><br><span class="line">                BigDecimal prize;</span><br><span class="line">                <span class="keyword">if</span>(count == <span class="number">1</span>)&#123;</span><br><span class="line">                    prize = money;</span><br><span class="line">                &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                    <span class="comment">//获取抽奖范围</span></span><br><span class="line">                    <span class="type">double</span> <span class="variable">bounds</span> <span class="operator">=</span> money.subtract(BigDecimal.valueOf(count-<span class="number">1</span>).multiply(MIN)).doubleValue();</span><br><span class="line">                    <span class="type">Random</span> <span class="variable">r</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Random</span>();</span><br><span class="line">                    <span class="comment">//抽奖金额</span></span><br><span class="line">                    prize = BigDecimal.valueOf(r.nextDouble(bounds));</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="comment">//设置抽中红包，小数点保留两位，四舍五入</span></span><br><span class="line">                prize = prize.setScale(<span class="number">2</span>,RoundingMode.HALF_UP);</span><br><span class="line">                <span class="comment">//在总金额中去掉对应的钱</span></span><br><span class="line">                money = money.subtract(prize);</span><br><span class="line">                <span class="comment">//红包少了一个</span></span><br><span class="line">                count--;</span><br><span class="line">                <span class="comment">//输出红包信息</span></span><br><span class="line">                System.out.println(getName() + <span class="string">&quot;抽中了&quot;</span> + prize + <span class="string">&quot;元&quot;</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Test</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">/*</span></span><br><span class="line"><span class="comment">            微信中的抢红包也用到了多线程。</span></span><br><span class="line"><span class="comment">            假设：100块，分成了3个包，现在有5个人去抢。</span></span><br><span class="line"><span class="comment">            其中，红包是共享数据。</span></span><br><span class="line"><span class="comment">            5个人是5条线程。</span></span><br><span class="line"><span class="comment">            打印结果如下：</span></span><br><span class="line"><span class="comment">            	XXX抢到了XXX元</span></span><br><span class="line"><span class="comment">            	XXX抢到了XXX元</span></span><br><span class="line"><span class="comment">            	XXX抢到了XXX元</span></span><br><span class="line"><span class="comment">            	XXX没抢到</span></span><br><span class="line"><span class="comment">            	XXX没抢到</span></span><br><span class="line"><span class="comment">        */</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="type">MyThread</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread</span>();</span><br><span class="line">        <span class="type">MyThread</span> <span class="variable">t2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread</span>();</span><br><span class="line">        <span class="type">MyThread</span> <span class="variable">t3</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread</span>();</span><br><span class="line">        <span class="type">MyThread</span> <span class="variable">t4</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread</span>();</span><br><span class="line">        <span class="type">MyThread</span> <span class="variable">t5</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread</span>();</span><br><span class="line"></span><br><span class="line">        t1.setName(<span class="string">&quot;小A&quot;</span>);</span><br><span class="line">        t2.setName(<span class="string">&quot;小QQ&quot;</span>);</span><br><span class="line">        t3.setName(<span class="string">&quot;小哈哈&quot;</span>);</span><br><span class="line">        t4.setName(<span class="string">&quot;小诗诗&quot;</span>);</span><br><span class="line">        t5.setName(<span class="string">&quot;小丹丹&quot;</span>);</span><br><span class="line"></span><br><span class="line">        t1.start();</span><br><span class="line">        t2.start();</span><br><span class="line">        t3.start();</span><br><span class="line">        t4.start();</span><br><span class="line">        t5.start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="练习五：抽奖箱"><a href="#练习五：抽奖箱" class="headerlink" title="练习五：抽奖箱"></a>练习五：抽奖箱</h3><p>需求：</p>
<p>​    有一个抽奖池,该抽奖池中存放了奖励的金额,该抽奖池中的奖项为 {10,5,20,50,100,200,500,800,2,80,300,700}; </p>
<p>创建两个抽奖箱(线程)设置线程名称分别为“抽奖箱1”，“抽奖箱2” </p>
<p>随机从抽奖池中获取奖项元素并打印在控制台上,格式如下:</p>
<p>​               每次抽出一个奖项就打印一个(随机)</p>
<p>​        抽奖箱1 又产生了一个 10 元大奖</p>
<pre><code>      抽奖箱1 又产生了一个 100 元大奖

      抽奖箱1 又产生了一个 200 元大奖

      抽奖箱1 又产生了一个 800 元大奖  
</code></pre><p>​        抽奖箱2 又产生了一个 700 元大奖  </p>
<pre><code>      .....
</code></pre><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyThread</span> <span class="keyword">extends</span> <span class="title class_">Thread</span> &#123;</span><br><span class="line"></span><br><span class="line">    ArrayList&lt;Integer&gt; list;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">MyThread</span><span class="params">(ArrayList&lt;Integer&gt; list)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.list = list;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">//1.循环</span></span><br><span class="line">        <span class="comment">//2.同步代码块</span></span><br><span class="line">        <span class="comment">//3.判断</span></span><br><span class="line">        <span class="comment">//4.判断</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">while</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">            <span class="keyword">synchronized</span> (MyThread.class) &#123;</span><br><span class="line">                <span class="keyword">if</span> (list.size() == <span class="number">0</span>) &#123;</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="comment">//继续抽奖</span></span><br><span class="line">                    Collections.shuffle(list);</span><br><span class="line">                    <span class="type">int</span> <span class="variable">prize</span> <span class="operator">=</span> list.remove(<span class="number">0</span>);</span><br><span class="line">                    System.out.println(getName() + <span class="string">&quot;又产生了一个&quot;</span> + prize + <span class="string">&quot;元大奖&quot;</span>);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                Thread.sleep(<span class="number">10</span>);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Test</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">/*</span></span><br><span class="line"><span class="comment">            有一个抽奖池,该抽奖池中存放了奖励的金额,该抽奖池中的奖项为 &#123;10,5,20,50,100,200,500,800,2,80,300,700&#125;;</span></span><br><span class="line"><span class="comment">            创建两个抽奖箱(线程)设置线程名称分别为“抽奖箱1”，“抽奖箱2”</span></span><br><span class="line"><span class="comment">            随机从抽奖池中获取奖项元素并打印在控制台上,格式如下:</span></span><br><span class="line"><span class="comment">                             每次抽出一个奖项就打印一个(随机)</span></span><br><span class="line"><span class="comment">            	抽奖箱1 又产生了一个 10 元大奖</span></span><br><span class="line"><span class="comment">            	抽奖箱1 又产生了一个 100 元大奖</span></span><br><span class="line"><span class="comment">            	抽奖箱1 又产生了一个 200 元大奖</span></span><br><span class="line"><span class="comment">            	抽奖箱1 又产生了一个 800 元大奖</span></span><br><span class="line"><span class="comment">            	抽奖箱2 又产生了一个 700 元大奖</span></span><br><span class="line"><span class="comment">            	.....</span></span><br><span class="line"><span class="comment">        */</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">//创建奖池</span></span><br><span class="line">        ArrayList&lt;Integer&gt; list = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">        Collections.addAll(list,<span class="number">10</span>,<span class="number">5</span>,<span class="number">20</span>,<span class="number">50</span>,<span class="number">100</span>,<span class="number">200</span>,<span class="number">500</span>,<span class="number">800</span>,<span class="number">2</span>,<span class="number">80</span>,<span class="number">300</span>,<span class="number">700</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//创建线程</span></span><br><span class="line">        <span class="type">MyThread</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread</span>(list);</span><br><span class="line">        <span class="type">MyThread</span> <span class="variable">t2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread</span>(list);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//设置名字</span></span><br><span class="line">        t1.setName(<span class="string">&quot;抽奖箱1&quot;</span>);</span><br><span class="line">        t2.setName(<span class="string">&quot;抽奖箱2&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//启动线程</span></span><br><span class="line">        t1.start();</span><br><span class="line">        t2.start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="练习六：多线程统计并求最大值"><a href="#练习六：多线程统计并求最大值" class="headerlink" title="练习六：多线程统计并求最大值"></a>练习六：多线程统计并求最大值</h3><p>需求：</p>
<p>​    在上一题基础上继续完成如下需求：</p>
<p>​     每次抽的过程中，不打印，抽完时一次性打印(随机)</p>
<p>​     在此次抽奖过程中，抽奖箱1总共产生了6个奖项。</p>
<p>​              分别为：10,20,100,500,2,300最高奖项为300元，总计额为932元</p>
<p>​     在此次抽奖过程中，抽奖箱2总共产生了6个奖项。</p>
<p>​              分别为：5,50,200,800,80,700最高奖项为800元，总计额为1835元</p>
<p>解决方案一：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyThread</span> <span class="keyword">extends</span> <span class="title class_">Thread</span> &#123;</span><br><span class="line"></span><br><span class="line">    ArrayList&lt;Integer&gt; list;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">MyThread</span><span class="params">(ArrayList&lt;Integer&gt; list)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.list = list;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//线程一</span></span><br><span class="line">    <span class="keyword">static</span> ArrayList&lt;Integer&gt; list1 = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">    <span class="comment">//线程二</span></span><br><span class="line">    <span class="keyword">static</span> ArrayList&lt;Integer&gt; list2 = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">while</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">            <span class="keyword">synchronized</span> (MyThread.class) &#123;</span><br><span class="line">                <span class="keyword">if</span> (list.size() == <span class="number">0</span>) &#123;</span><br><span class="line">                    <span class="keyword">if</span>(<span class="string">&quot;抽奖箱1&quot;</span>.equals(getName()))&#123;</span><br><span class="line">                        System.out.println(<span class="string">&quot;抽奖箱1&quot;</span> + list1);</span><br><span class="line">                    &#125;<span class="keyword">else</span> &#123;</span><br><span class="line">                        System.out.println(<span class="string">&quot;抽奖箱2&quot;</span> + list2);</span><br><span class="line">                    &#125;</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="comment">//继续抽奖</span></span><br><span class="line">                    Collections.shuffle(list);</span><br><span class="line">                    <span class="type">int</span> <span class="variable">prize</span> <span class="operator">=</span> list.remove(<span class="number">0</span>);</span><br><span class="line">                    <span class="keyword">if</span>(<span class="string">&quot;抽奖箱1&quot;</span>.equals(getName()))&#123;</span><br><span class="line">                        list1.add(prize);</span><br><span class="line">                    &#125;<span class="keyword">else</span> &#123;</span><br><span class="line">                        list2.add(prize);</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                Thread.sleep(<span class="number">10</span>);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Test</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">/*</span></span><br><span class="line"><span class="comment">            有一个抽奖池,该抽奖池中存放了奖励的金额,该抽奖池中的奖项为 &#123;10,5,20,50,100,200,500,800,2,80,300,700&#125;;</span></span><br><span class="line"><span class="comment">            创建两个抽奖箱(线程)设置线程名称分别为“抽奖箱1”，“抽奖箱2”</span></span><br><span class="line"><span class="comment">            随机从抽奖池中获取奖项元素并打印在控制台上,格式如下:</span></span><br><span class="line"><span class="comment">            每次抽的过程中，不打印，抽完时一次性打印(随机)    在此次抽奖过程中，抽奖箱1总共产生了6个奖项。</span></span><br><span class="line"><span class="comment">                分别为：10,20,100,500,2,300最高奖项为300元，总计额为932元</span></span><br><span class="line"><span class="comment">            在此次抽奖过程中，抽奖箱2总共产生了6个奖项。</span></span><br><span class="line"><span class="comment">                分别为：5,50,200,800,80,700最高奖项为800元，总计额为1835元</span></span><br><span class="line"><span class="comment">        */</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">//创建奖池</span></span><br><span class="line">        ArrayList&lt;Integer&gt; list = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">        Collections.addAll(list,<span class="number">10</span>,<span class="number">5</span>,<span class="number">20</span>,<span class="number">50</span>,<span class="number">100</span>,<span class="number">200</span>,<span class="number">500</span>,<span class="number">800</span>,<span class="number">2</span>,<span class="number">80</span>,<span class="number">300</span>,<span class="number">700</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//创建线程</span></span><br><span class="line">        <span class="type">MyThread</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread</span>(list);</span><br><span class="line">        <span class="type">MyThread</span> <span class="variable">t2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread</span>(list);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//设置名字</span></span><br><span class="line">        t1.setName(<span class="string">&quot;抽奖箱1&quot;</span>);</span><br><span class="line">        t2.setName(<span class="string">&quot;抽奖箱2&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//启动线程</span></span><br><span class="line">        t1.start();</span><br><span class="line">        t2.start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>解决方案二：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyThread</span> <span class="keyword">extends</span> <span class="title class_">Thread</span> &#123;</span><br><span class="line"></span><br><span class="line">    ArrayList&lt;Integer&gt; list;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">MyThread</span><span class="params">(ArrayList&lt;Integer&gt; list)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.list = list;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        ArrayList&lt;Integer&gt; boxList = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();<span class="comment">//1 //2</span></span><br><span class="line">        <span class="keyword">while</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">            <span class="keyword">synchronized</span> (MyThread.class) &#123;</span><br><span class="line">                <span class="keyword">if</span> (list.size() == <span class="number">0</span>) &#123;</span><br><span class="line">                    System.out.println(getName() + boxList);</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="comment">//继续抽奖</span></span><br><span class="line">                    Collections.shuffle(list);</span><br><span class="line">                    <span class="type">int</span> <span class="variable">prize</span> <span class="operator">=</span> list.remove(<span class="number">0</span>);</span><br><span class="line">                    boxList.add(prize);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                Thread.sleep(<span class="number">10</span>);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Test</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">/*</span></span><br><span class="line"><span class="comment">            有一个抽奖池,该抽奖池中存放了奖励的金额,该抽奖池中的奖项为 &#123;10,5,20,50,100,200,500,800,2,80,300,700&#125;;</span></span><br><span class="line"><span class="comment">            创建两个抽奖箱(线程)设置线程名称分别为“抽奖箱1”，“抽奖箱2”</span></span><br><span class="line"><span class="comment">            随机从抽奖池中获取奖项元素并打印在控制台上,格式如下:</span></span><br><span class="line"><span class="comment">            每次抽的过程中，不打印，抽完时一次性打印(随机)    在此次抽奖过程中，抽奖箱1总共产生了6个奖项。</span></span><br><span class="line"><span class="comment">                分别为：10,20,100,500,2,300最高奖项为300元，总计额为932元</span></span><br><span class="line"><span class="comment">            在此次抽奖过程中，抽奖箱2总共产生了6个奖项。</span></span><br><span class="line"><span class="comment">                分别为：5,50,200,800,80,700最高奖项为800元，总计额为1835元</span></span><br><span class="line"><span class="comment">        */</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">//创建奖池</span></span><br><span class="line">        ArrayList&lt;Integer&gt; list = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">        Collections.addAll(list,<span class="number">10</span>,<span class="number">5</span>,<span class="number">20</span>,<span class="number">50</span>,<span class="number">100</span>,<span class="number">200</span>,<span class="number">500</span>,<span class="number">800</span>,<span class="number">2</span>,<span class="number">80</span>,<span class="number">300</span>,<span class="number">700</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//创建线程</span></span><br><span class="line">        <span class="type">MyThread</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread</span>(list);</span><br><span class="line">        <span class="type">MyThread</span> <span class="variable">t2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread</span>(list);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="comment">//设置名字</span></span><br><span class="line">        t1.setName(<span class="string">&quot;抽奖箱1&quot;</span>);</span><br><span class="line">        t2.setName(<span class="string">&quot;抽奖箱2&quot;</span>);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="comment">//启动线程</span></span><br><span class="line">        t1.start();</span><br><span class="line">        t2.start();</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="练习七：多线程之间的比较"><a href="#练习七：多线程之间的比较" class="headerlink" title="练习七：多线程之间的比较"></a>练习七：多线程之间的比较</h3><p>需求：</p>
<p>​    在上一题基础上继续完成如下需求：</p>
<p>​    在此次抽奖过程中，抽奖箱1总共产生了6个奖项，分别为：10,20,100,500,2,300</p>
<pre><code>  最高奖项为300元，总计额为932元
</code></pre><p>​    在此次抽奖过程中，抽奖箱2总共产生了6个奖项，分别为：5,50,200,800,80,700</p>
<pre><code>  最高奖项为800元，总计额为1835元
</code></pre><p>​    在此次抽奖过程中,抽奖箱2中产生了最大奖项,该奖项金额为800元</p>
<p>​    以上打印效果只是数据模拟,实际代码运行的效果会有差异</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyCallable</span> <span class="keyword">implements</span> <span class="title class_">Callable</span>&lt;Integer&gt; &#123;</span><br><span class="line"></span><br><span class="line">    ArrayList&lt;Integer&gt; list;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">MyCallable</span><span class="params">(ArrayList&lt;Integer&gt; list)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.list = list;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Integer <span class="title function_">call</span><span class="params">()</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        ArrayList&lt;Integer&gt; boxList = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();<span class="comment">//1 //2</span></span><br><span class="line">        <span class="keyword">while</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">            <span class="keyword">synchronized</span> (MyCallable.class) &#123;</span><br><span class="line">                <span class="keyword">if</span> (list.size() == <span class="number">0</span>) &#123;</span><br><span class="line">                    System.out.println(Thread.currentThread().getName() + boxList);</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="comment">//继续抽奖</span></span><br><span class="line">                    Collections.shuffle(list);</span><br><span class="line">                    <span class="type">int</span> <span class="variable">prize</span> <span class="operator">=</span> list.remove(<span class="number">0</span>);</span><br><span class="line">                    boxList.add(prize);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            Thread.sleep(<span class="number">10</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//把集合中的最大值返回</span></span><br><span class="line">        <span class="keyword">if</span>(boxList.size() == <span class="number">0</span>)&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            <span class="keyword">return</span> Collections.max(boxList);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">package</span> com.itheima.test7;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.ArrayList;</span><br><span class="line"><span class="keyword">import</span> java.util.Collections;</span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.ExecutionException;</span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.FutureTask;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Test</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> ExecutionException, InterruptedException &#123;</span><br><span class="line">        <span class="comment">/*</span></span><br><span class="line"><span class="comment">            有一个抽奖池,该抽奖池中存放了奖励的金额,该抽奖池中的奖项为 &#123;10,5,20,50,100,200,500,800,2,80,300,700&#125;;</span></span><br><span class="line"><span class="comment">            创建两个抽奖箱(线程)设置线程名称分别为    &quot;抽奖箱1&quot;, &quot;抽奖箱2&quot;</span></span><br><span class="line"><span class="comment">            随机从抽奖池中获取奖项元素并打印在控制台上,格式如下:</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">            在此次抽奖过程中，抽奖箱1总共产生了6个奖项，分别为：10,20,100,500,2,300</span></span><br><span class="line"><span class="comment">        	    最高奖项为300元，总计额为932元</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">            在此次抽奖过程中，抽奖箱2总共产生了6个奖项，分别为：5,50,200,800,80,700</span></span><br><span class="line"><span class="comment">            	最高奖项为800元，总计额为1835元</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">            在此次抽奖过程中,抽奖箱2中产生了最大奖项,该奖项金额为800元</span></span><br><span class="line"><span class="comment">            核心逻辑：获取线程抽奖的最大值（看成是线程运行的结果）</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">            以上打印效果只是数据模拟,实际代码运行的效果会有差异</span></span><br><span class="line"><span class="comment">        */</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">//创建奖池</span></span><br><span class="line">        ArrayList&lt;Integer&gt; list = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">        Collections.addAll(list,<span class="number">10</span>,<span class="number">5</span>,<span class="number">20</span>,<span class="number">50</span>,<span class="number">100</span>,<span class="number">200</span>,<span class="number">500</span>,<span class="number">800</span>,<span class="number">2</span>,<span class="number">80</span>,<span class="number">300</span>,<span class="number">700</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//创建多线程要运行的参数对象</span></span><br><span class="line">        <span class="type">MyCallable</span> <span class="variable">mc</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyCallable</span>(list);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//创建多线程运行结果的管理者对象</span></span><br><span class="line">        <span class="comment">//线程一</span></span><br><span class="line">        FutureTask&lt;Integer&gt; ft1 = <span class="keyword">new</span> <span class="title class_">FutureTask</span>&lt;&gt;(mc);</span><br><span class="line">        <span class="comment">//线程二</span></span><br><span class="line">        FutureTask&lt;Integer&gt; ft2 = <span class="keyword">new</span> <span class="title class_">FutureTask</span>&lt;&gt;(mc);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//创建线程对象</span></span><br><span class="line">        <span class="type">Thread</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(ft1);</span><br><span class="line">        <span class="type">Thread</span> <span class="variable">t2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(ft2);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//设置名字</span></span><br><span class="line">        t1.setName(<span class="string">&quot;抽奖箱1&quot;</span>);</span><br><span class="line">        t2.setName(<span class="string">&quot;抽奖箱2&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//开启线程</span></span><br><span class="line">        t1.start();</span><br><span class="line">        t2.start();</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="type">Integer</span> <span class="variable">max1</span> <span class="operator">=</span> ft1.get();</span><br><span class="line">        <span class="type">Integer</span> <span class="variable">max2</span> <span class="operator">=</span> ft2.get();</span><br><span class="line"></span><br><span class="line">        System.out.println(max1);</span><br><span class="line">        System.out.println(max2);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//在此次抽奖过程中,抽奖箱2中产生了最大奖项,该奖项金额为800元</span></span><br><span class="line">        <span class="keyword">if</span>(max1 == <span class="literal">null</span>)&#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;在此次抽奖过程中,抽奖箱2中产生了最大奖项,该奖项金额为&quot;</span>+max2+<span class="string">&quot;元&quot;</span>);</span><br><span class="line">        &#125;<span class="keyword">else</span> <span class="keyword">if</span>(max2 == <span class="literal">null</span>)&#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;在此次抽奖过程中,抽奖箱1中产生了最大奖项,该奖项金额为&quot;</span>+max1+<span class="string">&quot;元&quot;</span>);</span><br><span class="line">        &#125;<span class="keyword">else</span> <span class="keyword">if</span>(max1 &gt; max2)&#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;在此次抽奖过程中,抽奖箱1中产生了最大奖项,该奖项金额为&quot;</span>+max1+<span class="string">&quot;元&quot;</span>);</span><br><span class="line">        &#125;<span class="keyword">else</span> <span class="keyword">if</span>(max1 &lt; max2)&#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;在此次抽奖过程中,抽奖箱2中产生了最大奖项,该奖项金额为&quot;</span>+max2+<span class="string">&quot;元&quot;</span>);</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;两者的最大奖项是一样的&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="2-原子性"><a href="#2-原子性" class="headerlink" title="2. 原子性"></a>2. 原子性</h2><h3 id="2-1-volatile-问题"><a href="#2-1-volatile-问题" class="headerlink" title="2.1 volatile-问题"></a>2.1 volatile-问题</h3><p><strong>代码分析 :</strong> </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.myvolatile;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Demo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">MyThread1</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread1</span>();</span><br><span class="line">        t1.setName(<span class="string">&quot;小路同学&quot;</span>);</span><br><span class="line">        t1.start();</span><br><span class="line"></span><br><span class="line">        <span class="type">MyThread2</span> <span class="variable">t2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread2</span>();</span><br><span class="line">        t2.setName(<span class="string">&quot;小皮同学&quot;</span>);</span><br><span class="line">        t2.start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.myvolatile;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Money</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="type">int</span> <span class="variable">money</span> <span class="operator">=</span> <span class="number">100000</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.myvolatile;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyThread1</span> <span class="keyword">extends</span>  <span class="title class_">Thread</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">while</span>(Money.money == <span class="number">100000</span>)&#123;</span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">&quot;结婚基金已经不是十万了&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.myvolatile;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyThread2</span> <span class="keyword">extends</span> <span class="title class_">Thread</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            Thread.sleep(<span class="number">10</span>);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        Money.money = <span class="number">90000</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p><strong>程序问题 :</strong>  女孩虽然知道结婚基金是十万，但是当基金的余额发生变化的时候，女孩无法知道最新的余额。</p>
<h3 id="2-2-volatile解决"><a href="#2-2-volatile解决" class="headerlink" title="2.2 volatile解决"></a>2.2 volatile解决</h3><p><strong>以上案例出现的问题 :</strong></p>
<p>​    当A线程修改了共享数据时，B线程没有及时获取到最新的值，如果还在使用原先的值，就会出现问题 </p>
<p>​    1，堆内存是唯一的，每一个线程都有自己的线程栈。</p>
<p>​    2 ，每一个线程在使用堆里面变量的时候，都会先拷贝一份到变量的副本中。</p>
<p>​    3 ，在线程中，每一次使用是从变量的副本中获取的。</p>
<p><strong>Volatile关键字 :</strong> 强制线程每次在使用的时候，都会看一下共享区域最新的值</p>
<p><strong>代码实现 :</strong> <strong>使用volatile关键字解决</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.myvolatile;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Demo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">MyThread1</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread1</span>();</span><br><span class="line">        t1.setName(<span class="string">&quot;小路同学&quot;</span>);</span><br><span class="line">        t1.start();</span><br><span class="line"></span><br><span class="line">        <span class="type">MyThread2</span> <span class="variable">t2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread2</span>();</span><br><span class="line">        t2.setName(<span class="string">&quot;小皮同学&quot;</span>);</span><br><span class="line">        t2.start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.myvolatile;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Money</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">volatile</span> <span class="type">int</span> <span class="variable">money</span> <span class="operator">=</span> <span class="number">100000</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.myvolatile;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyThread1</span> <span class="keyword">extends</span>  <span class="title class_">Thread</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">while</span>(Money.money == <span class="number">100000</span>)&#123;</span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">&quot;结婚基金已经不是十万了&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.myvolatile;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyThread2</span> <span class="keyword">extends</span> <span class="title class_">Thread</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            Thread.sleep(<span class="number">10</span>);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        Money.money = <span class="number">90000</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h3 id="2-3-synchronized解决"><a href="#2-3-synchronized解决" class="headerlink" title="2.3 synchronized解决"></a>2.3 synchronized解决</h3><p><strong>synchronized解决 :</strong> </p>
<p>​    1 ，线程获得锁</p>
<p>​    2 ，清空变量副本</p>
<p>​    3 ，拷贝共享变量最新的值到变量副本中</p>
<p>​    4 ，执行代码</p>
<p>​    5 ，将修改后变量副本中的值赋值给共享数据</p>
<p>​    6 ，释放锁</p>
<p><strong>代码实现 :</strong> </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.myvolatile2;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Demo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">MyThread1</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread1</span>();</span><br><span class="line">        t1.setName(<span class="string">&quot;小路同学&quot;</span>);</span><br><span class="line">        t1.start();</span><br><span class="line"></span><br><span class="line">        <span class="type">MyThread2</span> <span class="variable">t2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread2</span>();</span><br><span class="line">        t2.setName(<span class="string">&quot;小皮同学&quot;</span>);</span><br><span class="line">        t2.start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.myvolatile2;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Money</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="type">Object</span> <span class="variable">lock</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Object</span>();</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">volatile</span> <span class="type">int</span> <span class="variable">money</span> <span class="operator">=</span> <span class="number">100000</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.myvolatile2;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyThread1</span> <span class="keyword">extends</span>  <span class="title class_">Thread</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">while</span>(<span class="literal">true</span>)&#123;</span><br><span class="line">            <span class="keyword">synchronized</span> (Money.lock)&#123;</span><br><span class="line">                <span class="keyword">if</span>(Money.money != <span class="number">100000</span>)&#123;</span><br><span class="line">                    System.out.println(<span class="string">&quot;结婚基金已经不是十万了&quot;</span>);</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.myvolatile2;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyThread2</span> <span class="keyword">extends</span> <span class="title class_">Thread</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">synchronized</span> (Money.lock) &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                Thread.sleep(<span class="number">10</span>);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            Money.money = <span class="number">90000</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="2-4-原子性"><a href="#2-4-原子性" class="headerlink" title="2.4 原子性"></a>2.4 原子性</h3><p><strong>概述 :</strong> 所谓的原子性是指在一次操作或者多次操作中，要么所有的操作全部都得到了执行并且不会受到任何因素的干扰而中断，要么所有的操作都不执行，多个操作是一个不可以分割的整体。</p>
<p><strong>代码实现 :</strong> </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.threadatom;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AtomDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">MyAtomThread</span> <span class="variable">atom</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyAtomThread</span>();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">100</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">new</span> <span class="title class_">Thread</span>(atom).start();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">MyAtomThread</span> <span class="keyword">implements</span> <span class="title class_">Runnable</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">volatile</span> <span class="type">int</span> <span class="variable">count</span> <span class="operator">=</span> <span class="number">0</span>; <span class="comment">//送冰淇淋的数量</span></span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">100</span>; i++) &#123;</span><br><span class="line">            <span class="comment">//1,从共享数据中读取数据到本线程栈中.</span></span><br><span class="line">            <span class="comment">//2,修改本线程栈中变量副本的值</span></span><br><span class="line">            <span class="comment">//3,会把本线程栈中变量副本的值赋值给共享数据.</span></span><br><span class="line">            count++;</span><br><span class="line">            System.out.println(<span class="string">&quot;已经送了&quot;</span> + count + <span class="string">&quot;个冰淇淋&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>代码总结 :</strong> count++ 不是一个原子性操作, 他在执行的过程中,有可能被其他线程打断</p>
<h3 id="2-5-volatile关键字不能保证原子性"><a href="#2-5-volatile关键字不能保证原子性" class="headerlink" title="2.5 volatile关键字不能保证原子性"></a>2.5 volatile关键字不能保证原子性</h3><p>解决方案 : 我们可以给count++操作添加锁，那么count++操作就是临界区中的代码，临界区中的代码一次只能被一个线程去执行，所以count++就变成了原子操作。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.threadatom2;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AtomDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">MyAtomThread</span> <span class="variable">atom</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyAtomThread</span>();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">100</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">new</span> <span class="title class_">Thread</span>(atom).start();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">MyAtomThread</span> <span class="keyword">implements</span> <span class="title class_">Runnable</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">volatile</span> <span class="type">int</span> <span class="variable">count</span> <span class="operator">=</span> <span class="number">0</span>; <span class="comment">//送冰淇淋的数量</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">Object</span> <span class="variable">lock</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Object</span>();</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">100</span>; i++) &#123;</span><br><span class="line">            <span class="comment">//1,从共享数据中读取数据到本线程栈中.</span></span><br><span class="line">            <span class="comment">//2,修改本线程栈中变量副本的值</span></span><br><span class="line">            <span class="comment">//3,会把本线程栈中变量副本的值赋值给共享数据.</span></span><br><span class="line">            <span class="keyword">synchronized</span> (lock) &#123;</span><br><span class="line">                count++;</span><br><span class="line">                System.out.println(<span class="string">&quot;已经送了&quot;</span> + count + <span class="string">&quot;个冰淇淋&quot;</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="2-6-原子性-AtomicInteger"><a href="#2-6-原子性-AtomicInteger" class="headerlink" title="2.6 原子性_AtomicInteger"></a>2.6 原子性_AtomicInteger</h3><p>概述：java从JDK1.5开始提供了java.util.concurrent.atomic包(简称Atomic包)，这个包中的原子操作类提供了一种用法简单，性能高效，线程安全地更新一个变量的方式。因为变</p>
<p>量的类型有很多种，所以在Atomic包里一共提供了13个类，属于4种类型的原子更新方式，分别是原子更新基本类型、原子更新数组、原子更新引用和原子更新属性(字段)。本次我们只讲解</p>
<p>使用原子的方式更新基本类型，使用原子的方式更新基本类型Atomic包提供了以下3个类：</p>
<p>AtomicBoolean： 原子更新布尔类型</p>
<p>AtomicInteger：   原子更新整型</p>
<p>AtomicLong：    原子更新长整型</p>
<p>以上3个类提供的方法几乎一模一样，所以本节仅以AtomicInteger为例进行讲解，AtomicInteger的常用方法如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="title function_">AtomicInteger</span><span class="params">()</span>：	   			    初始化一个默认值为<span class="number">0</span>的原子型Integer</span><br><span class="line"><span class="keyword">public</span> <span class="title function_">AtomicInteger</span><span class="params">(<span class="type">int</span> initialValue)</span>：  初始化一个指定值的原子型Integer</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> <span class="title function_">get</span><span class="params">()</span>:   			 				获取值</span><br><span class="line"><span class="type">int</span> <span class="title function_">getAndIncrement</span><span class="params">()</span>:      			 以原子方式将当前值加<span class="number">1</span>，注意，这里返回的是自增前的值。</span><br><span class="line"><span class="type">int</span> <span class="title function_">incrementAndGet</span><span class="params">()</span>:     				 以原子方式将当前值加<span class="number">1</span>，注意，这里返回的是自增后的值。</span><br><span class="line"><span class="type">int</span> <span class="title function_">addAndGet</span><span class="params">(<span class="type">int</span> data)</span>:				 以原子方式将输入的数值与实例中的值（AtomicInteger里的value）相加，并返回结果。</span><br><span class="line"><span class="type">int</span> <span class="title function_">getAndSet</span><span class="params">(<span class="type">int</span> value)</span>:   			 以原子方式设置为newValue的值，并返回旧值。</span><br></pre></td></tr></table></figure>
<p><strong>代码实现 :</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.threadatom3;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.atomic.AtomicInteger;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyAtomIntergerDemo1</span> &#123;</span><br><span class="line"><span class="comment">//    public AtomicInteger()：	               初始化一个默认值为0的原子型Integer</span></span><br><span class="line"><span class="comment">//    public AtomicInteger(int initialValue)： 初始化一个指定值的原子型Integer</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">AtomicInteger</span> <span class="variable">ac</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">AtomicInteger</span>();</span><br><span class="line">        System.out.println(ac);</span><br><span class="line"></span><br><span class="line">        <span class="type">AtomicInteger</span> <span class="variable">ac2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">AtomicInteger</span>(<span class="number">10</span>);</span><br><span class="line">        System.out.println(ac2);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.threadatom3;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.Field;</span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.atomic.AtomicInteger;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyAtomIntergerDemo2</span> &#123;</span><br><span class="line"><span class="comment">//    int get():   		 		获取值</span></span><br><span class="line"><span class="comment">//    int getAndIncrement():     以原子方式将当前值加1，注意，这里返回的是自增前的值。</span></span><br><span class="line"><span class="comment">//    int incrementAndGet():     以原子方式将当前值加1，注意，这里返回的是自增后的值。</span></span><br><span class="line"><span class="comment">//    int addAndGet(int data):	 以原子方式将参数与对象中的值相加，并返回结果。</span></span><br><span class="line"><span class="comment">//    int getAndSet(int value):  以原子方式设置为newValue的值，并返回旧值。</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line"><span class="comment">//        AtomicInteger ac1 = new AtomicInteger(10);</span></span><br><span class="line"><span class="comment">//        System.out.println(ac1.get());</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//        AtomicInteger ac2 = new AtomicInteger(10);</span></span><br><span class="line"><span class="comment">//        int andIncrement = ac2.getAndIncrement();</span></span><br><span class="line"><span class="comment">//        System.out.println(andIncrement);</span></span><br><span class="line"><span class="comment">//        System.out.println(ac2.get());</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//        AtomicInteger ac3 = new AtomicInteger(10);</span></span><br><span class="line"><span class="comment">//        int i = ac3.incrementAndGet();</span></span><br><span class="line"><span class="comment">//        System.out.println(i);//自增后的值</span></span><br><span class="line"><span class="comment">//        System.out.println(ac3.get());</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//        AtomicInteger ac4 = new AtomicInteger(10);</span></span><br><span class="line"><span class="comment">//        int i = ac4.addAndGet(20);</span></span><br><span class="line"><span class="comment">//        System.out.println(i);</span></span><br><span class="line"><span class="comment">//        System.out.println(ac4.get());</span></span><br><span class="line"></span><br><span class="line">        <span class="type">AtomicInteger</span> <span class="variable">ac5</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">AtomicInteger</span>(<span class="number">100</span>);</span><br><span class="line">        <span class="type">int</span> <span class="variable">andSet</span> <span class="operator">=</span> ac5.getAndSet(<span class="number">20</span>);</span><br><span class="line">        System.out.println(andSet);</span><br><span class="line">        System.out.println(ac5.get());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="2-7-AtomicInteger-内存解析"><a href="#2-7-AtomicInteger-内存解析" class="headerlink" title="2.7 AtomicInteger-内存解析"></a>2.7 AtomicInteger-内存解析</h3><p><strong>AtomicInteger原理 :</strong> 自旋锁  + CAS 算法</p>
<p><strong>CAS算法：</strong></p>
<p>​    有3个操作数（内存值V， 旧的预期值A，要修改的值B）</p>
<p>​    当旧的预期值A == 内存值   此时修改成功，将V改为B                 </p>
<p>​    当旧的预期值A！=内存值   此时修改失败，不做任何操作                 </p>
<p>​    并重新获取现在的最新值（这个重新获取的动作就是自旋）</p>
<h3 id="2-8-AtomicInteger-源码解析"><a href="#2-8-AtomicInteger-源码解析" class="headerlink" title="2.8 AtomicInteger-源码解析"></a>2.8 AtomicInteger-源码解析</h3><p><strong>代码实现 :</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.threadatom4;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AtomDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">MyAtomThread</span> <span class="variable">atom</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyAtomThread</span>();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">100</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">new</span> <span class="title class_">Thread</span>(atom).start();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.threadatom4;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.atomic.AtomicInteger;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyAtomThread</span> <span class="keyword">implements</span> <span class="title class_">Runnable</span> &#123;</span><br><span class="line">    <span class="comment">//private volatile int count = 0; //送冰淇淋的数量</span></span><br><span class="line">    <span class="comment">//private Object lock = new Object();</span></span><br><span class="line">    <span class="type">AtomicInteger</span> <span class="variable">ac</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">AtomicInteger</span>(<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">100</span>; i++) &#123;</span><br><span class="line">            <span class="comment">//1,从共享数据中读取数据到本线程栈中.</span></span><br><span class="line">            <span class="comment">//2,修改本线程栈中变量副本的值</span></span><br><span class="line">            <span class="comment">//3,会把本线程栈中变量副本的值赋值给共享数据.</span></span><br><span class="line">            <span class="comment">//synchronized (lock) &#123;</span></span><br><span class="line"><span class="comment">//                count++;</span></span><br><span class="line"><span class="comment">//                ac++;</span></span><br><span class="line">            <span class="type">int</span> <span class="variable">count</span> <span class="operator">=</span> ac.incrementAndGet();</span><br><span class="line">            System.out.println(<span class="string">&quot;已经送了&quot;</span> + count + <span class="string">&quot;个冰淇淋&quot;</span>);</span><br><span class="line">           <span class="comment">// &#125;</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p><strong>源码解析 :</strong> </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">//先自增，然后获取自增后的结果</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="type">int</span> <span class="title function_">incrementAndGet</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">//+ 1 自增后的结果</span></span><br><span class="line">        <span class="comment">//this 就表示当前的atomicInteger（值）</span></span><br><span class="line">        <span class="comment">//1    自增一次</span></span><br><span class="line">        <span class="keyword">return</span> U.getAndAddInt(<span class="built_in">this</span>, VALUE, <span class="number">1</span>) + <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="type">int</span> <span class="title function_">getAndAddInt</span><span class="params">(Object o, <span class="type">long</span> offset, <span class="type">int</span> delta)</span> &#123;</span><br><span class="line">        <span class="comment">//v 旧值</span></span><br><span class="line">        <span class="type">int</span> v;</span><br><span class="line">        <span class="comment">//自旋的过程</span></span><br><span class="line">        <span class="keyword">do</span> &#123;</span><br><span class="line">            <span class="comment">//不断的获取旧值</span></span><br><span class="line">            v = getIntVolatile(o, offset);</span><br><span class="line">            <span class="comment">//如果这个方法的返回值为false，那么继续自旋</span></span><br><span class="line">            <span class="comment">//如果这个方法的返回值为true，那么自旋结束</span></span><br><span class="line">            <span class="comment">//o 表示的就是内存值</span></span><br><span class="line">            <span class="comment">//v 旧值</span></span><br><span class="line">            <span class="comment">//v + delta 修改后的值</span></span><br><span class="line">        &#125; <span class="keyword">while</span> (!weakCompareAndSetInt(o, offset, v, v + delta));</span><br><span class="line">            <span class="comment">//作用：比较内存中的值，旧值是否相等，如果相等就把修改后的值写到内存中，返回true。表示修改成功。</span></span><br><span class="line">            <span class="comment">//                                 如果不相等，无法把修改后的值写到内存中，返回false。表示修改失败。</span></span><br><span class="line">            <span class="comment">//如果修改失败，那么继续自旋。</span></span><br><span class="line">        <span class="keyword">return</span> v;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="2-9-悲观锁和乐观锁"><a href="#2-9-悲观锁和乐观锁" class="headerlink" title="2.9 悲观锁和乐观锁"></a>2.9 悲观锁和乐观锁</h3><p><strong>synchronized和CAS的区别 :</strong> </p>
<p><strong>相同点：</strong>在多线程情况下，都可以保证共享数据的安全性。</p>
<p><strong>不同点：</strong>synchronized总是从最坏的角度出发，认为每次获取数据的时候，别人都有可能修改。所以在每                       次操作共享数据之前，都会上锁。（悲观锁）</p>
<p>​    cas是从乐观的角度出发，假设每次获取数据别人都不会修改，所以不会上锁。只不过在修改共享数据的时候，会检查一下，别人有没有修改过这个数据。</p>
<p>​    如果别人修改过，那么我再次获取现在最新的值。            </p>
<p>​     如果别人没有修改过，那么我现在直接修改共享数据的值.(乐观锁）</p>
<h2 id="3-并发工具类"><a href="#3-并发工具类" class="headerlink" title="3. 并发工具类"></a>3. 并发工具类</h2><h3 id="3-1-并发工具类-Hashtable"><a href="#3-1-并发工具类-Hashtable" class="headerlink" title="3.1 并发工具类-Hashtable"></a>3.1 并发工具类-Hashtable</h3><p>​    <strong>Hashtable出现的原因 :</strong> 在集合类中HashMap是比较常用的集合对象，但是HashMap是线程不安全的(多线程环境下可能会存在问题)。为了保证数据的安全性我们可以使用Hashtable，但是Hashtable的效率低下。</p>
<p><strong>代码实现 :</strong> </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.mymap;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.HashMap;</span><br><span class="line"><span class="keyword">import</span> java.util.Hashtable;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyHashtableDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">        Hashtable&lt;String, String&gt; hm = <span class="keyword">new</span> <span class="title class_">Hashtable</span>&lt;&gt;();</span><br><span class="line"></span><br><span class="line">        <span class="type">Thread</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">25</span>; i++) &#123;</span><br><span class="line">                hm.put(i + <span class="string">&quot;&quot;</span>, i + <span class="string">&quot;&quot;</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="type">Thread</span> <span class="variable">t2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">25</span>; i &lt; <span class="number">51</span>; i++) &#123;</span><br><span class="line">                hm.put(i + <span class="string">&quot;&quot;</span>, i + <span class="string">&quot;&quot;</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line">        t1.start();</span><br><span class="line">        t2.start();</span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">&quot;----------------------------&quot;</span>);</span><br><span class="line">        <span class="comment">//为了t1和t2能把数据全部添加完毕</span></span><br><span class="line">        Thread.sleep(<span class="number">1000</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//0-0 1-1 ..... 50- 50</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">51</span>; i++) &#123;</span><br><span class="line">            System.out.println(hm.get(i + <span class="string">&quot;&quot;</span>));</span><br><span class="line">        &#125;<span class="comment">//0 1 2 3 .... 50</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="3-2-并发工具类-ConcurrentHashMap基本使用"><a href="#3-2-并发工具类-ConcurrentHashMap基本使用" class="headerlink" title="3.2 并发工具类-ConcurrentHashMap基本使用"></a>3.2 并发工具类-ConcurrentHashMap基本使用</h3><p>​    <strong>ConcurrentHashMap出现的原因 :</strong> 在集合类中HashMap是比较常用的集合对象，但是HashMap是线程不安全的(多线程环境下可能会存在问题)。为了保证数据的安全性我们可以使用Hashtable，但是Hashtable的效率低下。</p>
<p>基于以上两个原因我们可以使用JDK1.5以后所提供的ConcurrentHashMap。</p>
<p><strong>体系结构 :</strong> </p>
<p><img src= "" data-lazy-src="/img/1591168965857.png" alt="1591168965857"></p>
<p><strong>总结 :</strong> </p>
<p>​    1 ，HashMap是线程不安全的。多线程环境下会有数据安全问题</p>
<p>​    2 ，Hashtable是线程安全的，但是会将整张表锁起来，效率低下</p>
<p>​    3，ConcurrentHashMap也是线程安全的，效率较高。     在JDK7和JDK8中，底层原理不一样。</p>
<p><strong>代码实现 :</strong> </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.mymap;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.Hashtable;</span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.ConcurrentHashMap;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyConcurrentHashMapDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">        ConcurrentHashMap&lt;String, String&gt; hm = <span class="keyword">new</span> <span class="title class_">ConcurrentHashMap</span>&lt;&gt;(<span class="number">100</span>);</span><br><span class="line"></span><br><span class="line">        <span class="type">Thread</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">25</span>; i++) &#123;</span><br><span class="line">                hm.put(i + <span class="string">&quot;&quot;</span>, i + <span class="string">&quot;&quot;</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="type">Thread</span> <span class="variable">t2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">25</span>; i &lt; <span class="number">51</span>; i++) &#123;</span><br><span class="line">                hm.put(i + <span class="string">&quot;&quot;</span>, i + <span class="string">&quot;&quot;</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line">        t1.start();</span><br><span class="line">        t2.start();</span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">&quot;----------------------------&quot;</span>);</span><br><span class="line">        <span class="comment">//为了t1和t2能把数据全部添加完毕</span></span><br><span class="line">        Thread.sleep(<span class="number">1000</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//0-0 1-1 ..... 50- 50</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">51</span>; i++) &#123;</span><br><span class="line">            System.out.println(hm.get(i + <span class="string">&quot;&quot;</span>));</span><br><span class="line">        &#125;<span class="comment">//0 1 2 3 .... 50</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="3-3-并发工具类-ConcurrentHashMap1-7原理"><a href="#3-3-并发工具类-ConcurrentHashMap1-7原理" class="headerlink" title="3.3 并发工具类-ConcurrentHashMap1.7原理"></a>3.3 并发工具类-ConcurrentHashMap1.7原理</h3><p><img src= "" data-lazy-src="/img/1591169254280.png" alt="1591169254280"></p>
<h3 id="3-4-并发工具类-ConcurrentHashMap1-8原理"><a href="#3-4-并发工具类-ConcurrentHashMap1-8原理" class="headerlink" title="3.4 并发工具类-ConcurrentHashMap1.8原理"></a>3.4 并发工具类-ConcurrentHashMap1.8原理</h3><p><img src= "" data-lazy-src="/img/1591169338256.png" alt="1591169338256"></p>
<p><strong>总结 :</strong> </p>
<p>​    1，如果使用空参构造创建ConcurrentHashMap对象，则什么事情都不做。     在第一次添加元素的时候创建哈希表</p>
<p>​    2，计算当前元素应存入的索引。</p>
<p>​    3，如果该索引位置为null，则利用cas算法，将本结点添加到数组中。</p>
<p>​    4，如果该索引位置不为null，则利用volatile关键字获得当前位置最新的结点地址，挂在他下面，变成链表。        </p>
<p>​    5，当链表的长度大于等于8时，自动转换成红黑树6，以链表或者红黑树头结点为锁对象，配合悲观锁保证多线程操作集合时数据的安全性</p>
<h3 id="3-5-并发工具类-CountDownLatch"><a href="#3-5-并发工具类-CountDownLatch" class="headerlink" title="3.5 并发工具类-CountDownLatch"></a>3.5 并发工具类-CountDownLatch</h3><p><strong>CountDownLatch类 :</strong>         </p>
<div class="table-container">
<table>
<thead>
<tr>
<th>方法</th>
<th>解释</th>
</tr>
</thead>
<tbody>
<tr>
<td>public CountDownLatch(int count)</td>
<td>参数传递线程数，表示等待线程数量</td>
</tr>
<tr>
<td>public void await()</td>
<td>让线程等待</td>
</tr>
<tr>
<td>public void countDown()</td>
<td>当前线程执行完毕</td>
</tr>
</tbody>
</table>
</div>
<p><strong>使用场景：</strong> 让某一条线程等待其他线程执行完毕之后再执行</p>
<p><strong>代码实现 :</strong> </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.mycountdownlatch;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.CountDownLatch;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ChileThread1</span> <span class="keyword">extends</span> <span class="title class_">Thread</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> CountDownLatch countDownLatch;</span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">ChileThread1</span><span class="params">(CountDownLatch countDownLatch)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.countDownLatch = countDownLatch;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">//1.吃饺子</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">1</span>; i &lt;= <span class="number">10</span>; i++) &#123;</span><br><span class="line">            System.out.println(getName() + <span class="string">&quot;在吃第&quot;</span> + i + <span class="string">&quot;个饺子&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//2.吃完说一声</span></span><br><span class="line">        <span class="comment">//每一次countDown方法的时候，就让计数器-1</span></span><br><span class="line">        countDownLatch.countDown();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.mycountdownlatch;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.CountDownLatch;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ChileThread2</span> <span class="keyword">extends</span> <span class="title class_">Thread</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> CountDownLatch countDownLatch;</span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">ChileThread2</span><span class="params">(CountDownLatch countDownLatch)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.countDownLatch = countDownLatch;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">//1.吃饺子</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">1</span>; i &lt;= <span class="number">15</span>; i++) &#123;</span><br><span class="line">            System.out.println(getName() + <span class="string">&quot;在吃第&quot;</span> + i + <span class="string">&quot;个饺子&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//2.吃完说一声</span></span><br><span class="line">        <span class="comment">//每一次countDown方法的时候，就让计数器-1</span></span><br><span class="line">        countDownLatch.countDown();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.mycountdownlatch;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.CountDownLatch;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ChileThread3</span> <span class="keyword">extends</span> <span class="title class_">Thread</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> CountDownLatch countDownLatch;</span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">ChileThread3</span><span class="params">(CountDownLatch countDownLatch)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.countDownLatch = countDownLatch;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">//1.吃饺子</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">1</span>; i &lt;= <span class="number">20</span>; i++) &#123;</span><br><span class="line">            System.out.println(getName() + <span class="string">&quot;在吃第&quot;</span> + i + <span class="string">&quot;个饺子&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//2.吃完说一声</span></span><br><span class="line">        <span class="comment">//每一次countDown方法的时候，就让计数器-1</span></span><br><span class="line">        countDownLatch.countDown();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.mycountdownlatch;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.CountDownLatch;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MotherThread</span> <span class="keyword">extends</span> <span class="title class_">Thread</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> CountDownLatch countDownLatch;</span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">MotherThread</span><span class="params">(CountDownLatch countDownLatch)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.countDownLatch = countDownLatch;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">//1.等待</span></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">//当计数器变成0的时候，会自动唤醒这里等待的线程。</span></span><br><span class="line">            countDownLatch.await();</span><br><span class="line">        &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//2.收拾碗筷</span></span><br><span class="line">        System.out.println(<span class="string">&quot;妈妈在收拾碗筷&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.mycountdownlatch;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.CountDownLatch;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyCountDownLatchDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">//1.创建CountDownLatch的对象，需要传递给四个线程。</span></span><br><span class="line">        <span class="comment">//在底层就定义了一个计数器，此时计数器的值就是3</span></span><br><span class="line">        <span class="type">CountDownLatch</span> <span class="variable">countDownLatch</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">CountDownLatch</span>(<span class="number">3</span>);</span><br><span class="line">        <span class="comment">//2.创建四个线程对象并开启他们。</span></span><br><span class="line">        <span class="type">MotherThread</span> <span class="variable">motherThread</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MotherThread</span>(countDownLatch);</span><br><span class="line">        motherThread.start();</span><br><span class="line"></span><br><span class="line">        <span class="type">ChileThread1</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ChileThread1</span>(countDownLatch);</span><br><span class="line">        t1.setName(<span class="string">&quot;小明&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="type">ChileThread2</span> <span class="variable">t2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ChileThread2</span>(countDownLatch);</span><br><span class="line">        t2.setName(<span class="string">&quot;小红&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="type">ChileThread3</span> <span class="variable">t3</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ChileThread3</span>(countDownLatch);</span><br><span class="line">        t3.setName(<span class="string">&quot;小刚&quot;</span>);</span><br><span class="line"></span><br><span class="line">        t1.start();</span><br><span class="line">        t2.start();</span><br><span class="line">        t3.start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>总结 :</strong> </p>
<p>​    1. CountDownLatch(int count)：参数写等待线程的数量。并定义了一个计数器。</p>
<p>​    2. await()：让线程等待，当计数器为0时，会唤醒等待的线程</p>
<p>​    3. countDown()： 线程执行完毕时调用，会将计数器-1。</p>
<h3 id="3-6-并发工具类-Semaphore"><a href="#3-6-并发工具类-Semaphore" class="headerlink" title="3.6 并发工具类-Semaphore"></a>3.6 并发工具类-Semaphore</h3><p><strong>使用场景 :</strong> </p>
<p>​    可以控制访问特定资源的线程数量。</p>
<p><strong>实现步骤 :</strong> </p>
<p>​    1，需要有人管理这个通道</p>
<p>​    2，当有车进来了，发通行许可证</p>
<p>​    3，当车出去了，收回通行许可证</p>
<p>​    4，如果通行许可证发完了，那么其他车辆只能等着</p>
<p><strong>代码实现 :</strong> </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.mysemaphore;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.Semaphore;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyRunnable</span> <span class="keyword">implements</span> <span class="title class_">Runnable</span> &#123;</span><br><span class="line">    <span class="comment">//1.获得管理员对象，</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">Semaphore</span> <span class="variable">semaphore</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Semaphore</span>(<span class="number">2</span>);</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">//2.获得通行证</span></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            semaphore.acquire();</span><br><span class="line">            <span class="comment">//3.开始行驶</span></span><br><span class="line">            System.out.println(<span class="string">&quot;获得了通行证开始行驶&quot;</span>);</span><br><span class="line">            Thread.sleep(<span class="number">2000</span>);</span><br><span class="line">            System.out.println(<span class="string">&quot;归还通行证&quot;</span>);</span><br><span class="line">            <span class="comment">//4.归还通行证</span></span><br><span class="line">            semaphore.release();</span><br><span class="line">        &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.itheima.mysemaphore;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MySemaphoreDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">MyRunnable</span> <span class="variable">mr</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyRunnable</span>();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">100</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">new</span> <span class="title class_">Thread</span>(mr).start();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</article><div class="post-copyright"><div class="post-copyright__title"><span class="post-copyright-info"><h>JUC</h></span></div><div class="post-copyright__type"><span class="post-copyright-info"><a href="https://srs-blog.github.io/2025/04/11/JUC/">https://srs-blog.github.io/2025/04/11/JUC/</a></span></div><div class="post-copyright-m"><div class="post-copyright-m-info"><div class="post-copyright-a"><h>作者</h><div class="post-copyright-cc-info"><h>SRS</h></div></div><div class="post-copyright-c"><h>发布于</h><div class="post-copyright-cc-info"><h>2025-04-11</h></div></div><div class="post-copyright-u"><h>更新于</h><div class="post-copyright-cc-info"><h>2025-04-11</h></div></div><div class="post-copyright-c"><h>许可协议</h><div class="post-copyright-cc-info"><a class="icon" rel="noopener" target="_blank" title="Creative Commons" href="https://creativecommons.org/"><i class="fab fa-creative-commons"></i></a><a rel="noopener" target="_blank" title="CC BY-NC-SA 4.0" href="https://creativecommons.org/licenses/by-nc-sa/4.0/">CC BY-NC-SA 4.0</a></div></div></div></div></div><div class="tag_share"><div class="post-share"><div class="social-share" data-image="/img/bac-4.jpg" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/butterfly-extsrc/sharejs/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/sharejs/dist/js/social-share.min.js" defer></script></div></div><link rel="stylesheet" href="/css/coin.css" media="defer" onload="this.media='all'"/><div class="post-reward"><button class="tip-button reward-button"><span class="tip-button__text">不给糖就捣蛋</span><div class="coin-wrapper"><div class="coin"><div class="coin__middle"></div><div class="coin__back"></div><div class="coin__front"></div></div></div><div class="reward-main"><ul class="reward-all"><li class="reward-item"><a href="/img/skm.jpg" target="_blank"><img class="post-qr-code-img" src= "" data-lazy-src="/img/skm.jpg" alt="wechat"/></a><div class="post-qr-code-desc">wechat</div></li></ul></div></button></div><audio id="coinAudio" src="https://cdn.cbd.int/akilar-candyassets@1.0.36/audio/aowu.m4a"></audio><script defer="defer" src="/js/coin.js"></script><nav class="pagination-post" id="pagination"><a class="pagination-related" href="/2025/04/10/IO%E6%B5%81-%E5%AD%97%E8%8A%82%E6%B5%81-%E5%AD%97%E7%AC%A6%E6%B5%81/" title="IO流"><img class="cover" src= "" data-lazy-src="/img/bac-15.jpg" onerror="onerror=null;src='/img/404.jpg'" alt="cover of previous post"><div class="info"><div class="info-1"><div class="info-item-1">上一篇</div><div class="info-item-2">IO流</div></div><div class="info-2"><div class="info-item-1">1. IO概述 1.1 什么是IO生活中，你肯定经历过这样的场景。当你编辑一个文本文件，忘记了ctrl+s ，可能文件就白白编辑了。当你电脑上插入一个U盘，可以把一个视频，拷贝到你的电脑硬盘里。那么数据都是在哪些设备上的呢？键盘、内存、硬盘、外接设备等等。 我们把这种数据的传输，可以看做是一种数据的流动，按照流动的方向，以内存为基准，分为输入input 和输出output ，即流向内存是输入流，流出内存的输出流。 Java中I/O操作主要是指使用java.io包下的内容，进行输入、输出操作。输入也叫做读取数据，输出也叫做作写出数据。 1.2 IO的分类根据数据的流向分为：输入流和输出流。  输入流 ：把数据从其他设备上读取到内存中的流。  输出流 ：把数据从内存 中写出到其他设备上的流。  格局数据的类型分为：字节流和字符流。  字节流 ：以字节为单位，读写数据的流。 字符流 ：以字符为单位，读写数据的流。  1.3 IO的流向说明图解 1.4...</div></div></div></a><a class="pagination-related" href="/2025/04/11/%E5%A4%9A%E7%BA%BF%E7%A8%8B/" title="多线程"><img class="cover" src= "" data-lazy-src="/img/bac-7.jpg" onerror="onerror=null;src='/img/404.jpg'" alt="cover of next post"><div class="info text-right"><div class="info-1"><div class="info-item-1">下一篇</div><div class="info-item-2">多线程</div></div><div class="info-2"><div class="info-item-1">1.实现多线程1.1简单了解多线程【理解】是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多个线程，提升性能。  1.2并发和并行【理解】 并行：在同一时刻，有多个指令在多个CPU上同时执行。   并发：在同一时刻，有多个指令在单个CPU上交替执行。    1.3进程和线程【理解】 进程：是正在运行的程序 独立性：进程是一个能独立运行的基本单位，同时也是系统分配资源和调度的独立单位动态性：进程的实质是程序的一次执行过程，进程是动态产生，动态消亡的并发性：任何进程都可以同其他进程一起并发执行  线程：是进程中的单个顺序控制流，是一条执行路径 ​    单线程：一个进程如果只有一条执行路径，则称为单线程程序 ​    多线程：一个进程如果有多条执行路径，则称为多线程程序 ​       1.4实现多线程方式一：继承Thread类【应用】  方法介绍 | 方法名          | 说明                         || —————— | ————————————— || void run()   |...</div></div></div></a></nav><hr class="custom-hr"/><div id="post-comment"><div class="comment-head"><div class="comment-headline"><i class="fas fa-comments fa-fw"></i><span> 评论</span></div></div><div class="comment-wrap"><div><div id="twikoo-wrap"></div></div></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info text-center"><div class="author_top is-center"> </div><div class="card-info-avatar"><div class="avatar-img"><img src= "" data-lazy-src="/img/srs.jpg" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-status-box"><div class="author-status"><g-emoji class="g-emoji" alias="palm_tree" fallback-src="https://lskypro.acozycotage.net/LightPicture/2022/12/fe1dc0402e623096.jpg">🐟</g-emoji><span>认真摸鱼中</span></div></div></div><div class="author-info-name">SRS</div><div class="author-info-description">SRS的个人博客</div><div class="site-data"><a href="/archives/"><div class="headline">文章</div><div class="length-num">9</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">0</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">4</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/SRS-Blog"><i></i><span>前往小窝<i class="faa-passing animated" style="padding-left:20px;display:inline-block;vertical-align:middle;"><svg class="icon" style="height:28px;width:28px;fill:currentColor;position:relative;top:5px"><use xlink:href="#icon-xiaoqiche"></use></svg></i></span></a><div class="card-info-social-icons"><a class="social-icon faa-parent animated-hover" href="https://github.com/SRS-Blog" target="_blank" title="Github"><svg class="social_icon faa-tada" aria-hidden="true"><use xlink:href="#icon-github"></use></svg></a><a class="social-icon faa-parent animated-hover" href="mailto:SRS15303449212@163.com" target="_blank" title="邮件"><svg class="social_icon faa-tada" aria-hidden="true"><use xlink:href="#icon-mail"></use></svg></a><a class="social-icon faa-parent animated-hover" href="/img/wechat.jpg" target="_blank" title="微信"><svg class="social_icon faa-tada" aria-hidden="true"><use xlink:href="#icon-weixinmendian"></use></svg></a><a class="social-icon faa-parent animated-hover" href="https://res.abeim.cn/api/qq/?qq=1440761261" target="_blank" title="QQ"><svg class="social_icon faa-tada" aria-hidden="true"><use xlink:href="#icon-QQ"></use></svg></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><a class="faa-parent animated-hover"><svg class="faa-tada icon" style="height:30px;width:25px;fill:currentColor;position:relative;top:5px" aria-hidden="true"><use href="#icon-gonggao1"></use></svg></a><span>公告栏</span></div><div class="announcement_content"></div><div id="welcome-info"></div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span><span class="toc-percentage"></span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#1-%E7%BA%BF%E7%A8%8B%E6%B1%A0"><span class="toc-text">1. 线程池</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-1-%E7%BA%BF%E7%A8%8B%E7%8A%B6%E6%80%81%E4%BB%8B%E7%BB%8D"><span class="toc-text">1.1 线程状态介绍</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#1-2-%E7%BA%BF%E7%A8%8B%E6%B1%A0-%E5%9F%BA%E6%9C%AC%E5%8E%9F%E7%90%86"><span class="toc-text">1.2 线程池-基本原理</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#1-3-%E7%BA%BF%E7%A8%8B%E6%B1%A0-Executors%E9%BB%98%E8%AE%A4%E7%BA%BF%E7%A8%8B%E6%B1%A0"><span class="toc-text">1.3 线程池-Executors默认线程池</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#1-4-%E7%BA%BF%E7%A8%8B%E6%B1%A0-Executors%E5%88%9B%E5%BB%BA%E6%8C%87%E5%AE%9A%E4%B8%8A%E9%99%90%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%B1%A0"><span class="toc-text">1.4 线程池-Executors创建指定上限的线程池</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#1-5-%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BA%BF%E7%A8%8B%E6%B1%A0-ThreadPoolExecutor"><span class="toc-text">1.5 自定义线程池-ThreadPoolExecutor</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#1-6-%E7%BA%BF%E7%A8%8B%E6%B1%A0-%E5%8F%82%E6%95%B0%E8%AF%A6%E8%A7%A3"><span class="toc-text">1.6 线程池-参数详解</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#1-7-%E7%BA%BF%E7%A8%8B%E6%B1%A0-%E9%9D%9E%E9%BB%98%E8%AE%A4%E4%BB%BB%E5%8A%A1%E6%8B%92%E7%BB%9D%E7%AD%96%E7%95%A5"><span class="toc-text">1.7 线程池-非默认任务拒绝策略</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#1-8-%E7%BA%BF%E7%A8%8B%E6%B1%A0%E9%9C%80%E8%A6%81%E5%A4%9A%E5%A4%A7"><span class="toc-text">1.8 线程池需要多大</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%BB%BC%E5%90%88%E7%BB%83%E4%B9%A0"><span class="toc-text">2. 多线程综合练习</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%BB%83%E4%B9%A0%E4%B8%80%EF%BC%9A%E5%94%AE%E7%A5%A8"><span class="toc-text">练习一：售票</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%BB%83%E4%B9%A0%E4%BA%8C%EF%BC%9A%E8%B5%A0%E9%80%81%E7%A4%BC%E7%89%A9"><span class="toc-text">练习二：赠送礼物</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%BB%83%E4%B9%A0%E4%B8%89%EF%BC%9A%E6%89%93%E5%8D%B0%E6%95%B0%E5%AD%97"><span class="toc-text">练习三：打印数字</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%BB%83%E4%B9%A0%E5%9B%9B%EF%BC%9A%E6%8A%A2%E7%BA%A2%E5%8C%85"><span class="toc-text">练习四：抢红包</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%BB%83%E4%B9%A0%E4%BA%94%EF%BC%9A%E6%8A%BD%E5%A5%96%E7%AE%B1"><span class="toc-text">练习五：抽奖箱</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%BB%83%E4%B9%A0%E5%85%AD%EF%BC%9A%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%BB%9F%E8%AE%A1%E5%B9%B6%E6%B1%82%E6%9C%80%E5%A4%A7%E5%80%BC"><span class="toc-text">练习六：多线程统计并求最大值</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%BB%83%E4%B9%A0%E4%B8%83%EF%BC%9A%E5%A4%9A%E7%BA%BF%E7%A8%8B%E4%B9%8B%E9%97%B4%E7%9A%84%E6%AF%94%E8%BE%83"><span class="toc-text">练习七：多线程之间的比较</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-%E5%8E%9F%E5%AD%90%E6%80%A7"><span class="toc-text">2. 原子性</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#2-1-volatile-%E9%97%AE%E9%A2%98"><span class="toc-text">2.1 volatile-问题</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-2-volatile%E8%A7%A3%E5%86%B3"><span class="toc-text">2.2 volatile解决</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-3-synchronized%E8%A7%A3%E5%86%B3"><span class="toc-text">2.3 synchronized解决</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-4-%E5%8E%9F%E5%AD%90%E6%80%A7"><span class="toc-text">2.4 原子性</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-5-volatile%E5%85%B3%E9%94%AE%E5%AD%97%E4%B8%8D%E8%83%BD%E4%BF%9D%E8%AF%81%E5%8E%9F%E5%AD%90%E6%80%A7"><span class="toc-text">2.5 volatile关键字不能保证原子性</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-6-%E5%8E%9F%E5%AD%90%E6%80%A7-AtomicInteger"><span class="toc-text">2.6 原子性_AtomicInteger</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-7-AtomicInteger-%E5%86%85%E5%AD%98%E8%A7%A3%E6%9E%90"><span class="toc-text">2.7 AtomicInteger-内存解析</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-8-AtomicInteger-%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90"><span class="toc-text">2.8 AtomicInteger-源码解析</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-9-%E6%82%B2%E8%A7%82%E9%94%81%E5%92%8C%E4%B9%90%E8%A7%82%E9%94%81"><span class="toc-text">2.9 悲观锁和乐观锁</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-%E5%B9%B6%E5%8F%91%E5%B7%A5%E5%85%B7%E7%B1%BB"><span class="toc-text">3. 并发工具类</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#3-1-%E5%B9%B6%E5%8F%91%E5%B7%A5%E5%85%B7%E7%B1%BB-Hashtable"><span class="toc-text">3.1 并发工具类-Hashtable</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-2-%E5%B9%B6%E5%8F%91%E5%B7%A5%E5%85%B7%E7%B1%BB-ConcurrentHashMap%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8"><span class="toc-text">3.2 并发工具类-ConcurrentHashMap基本使用</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-3-%E5%B9%B6%E5%8F%91%E5%B7%A5%E5%85%B7%E7%B1%BB-ConcurrentHashMap1-7%E5%8E%9F%E7%90%86"><span class="toc-text">3.3 并发工具类-ConcurrentHashMap1.7原理</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-4-%E5%B9%B6%E5%8F%91%E5%B7%A5%E5%85%B7%E7%B1%BB-ConcurrentHashMap1-8%E5%8E%9F%E7%90%86"><span class="toc-text">3.4 并发工具类-ConcurrentHashMap1.8原理</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-5-%E5%B9%B6%E5%8F%91%E5%B7%A5%E5%85%B7%E7%B1%BB-CountDownLatch"><span class="toc-text">3.5 并发工具类-CountDownLatch</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-6-%E5%B9%B6%E5%8F%91%E5%B7%A5%E5%85%B7%E7%B1%BB-Semaphore"><span class="toc-text">3.6 并发工具类-Semaphore</span></a></li></ol></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><a class="faa-parent animated-hover"><svg class="faa-tada icon" style="height:30px;width:25px;fill:currentColor;position:relative;top:5px" aria-hidden="true"><use href="#icon-zuixinshijuan"></use></svg></a><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/2025/04/13/%E8%8B%A5%E4%BE%9D%E5%9F%BA%E7%A1%80%E5%BA%94%E7%94%A8%E7%AF%87/" title="若依框架"><img src= "" data-lazy-src="/img/bac-1.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="若依框架"/></a><div class="content"><a class="title" href="/2025/04/13/%E8%8B%A5%E4%BE%9D%E5%9F%BA%E7%A1%80%E5%BA%94%E7%94%A8%E7%AF%87/" title="若依框架">若依框架</a><time datetime="2025-04-12T16:00:00.000Z" title="发表于 2025-04-13 00:00:00">2025-04-13</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2025/04/11/JUC/" title="JUC"><img src= "" data-lazy-src="/img/bac-4.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="JUC"/></a><div class="content"><a class="title" href="/2025/04/11/JUC/" title="JUC">JUC</a><time datetime="2025-04-10T16:00:00.000Z" title="发表于 2025-04-11 00:00:00">2025-04-11</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2025/04/11/%E5%A4%9A%E7%BA%BF%E7%A8%8B/" title="多线程"><img src= "" data-lazy-src="/img/bac-7.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="多线程"/></a><div class="content"><a class="title" href="/2025/04/11/%E5%A4%9A%E7%BA%BF%E7%A8%8B/" title="多线程">多线程</a><time datetime="2025-04-10T16:00:00.000Z" title="发表于 2025-04-11 00:00:00">2025-04-11</time></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div id="ft"><div class="ft-item-1"><div class="t-top"><div class="t-t-l"><p class="ft-t t-l-t">格言🧬</p><div class="bg-ad"><div> 不必匆忙赶路，慢下来感受阳光与微风。生活不会永远完美，但总有不期而遇的温暖。累了就停一停，但别忘记，你走过的每一步都在铺垫未来的惊喜✨</div><div class="btn-xz-box"><a class="btn-xz" target="_blank" rel="noopener" href="https://raw.githubusercontent.com/SRS-Blog/SRS-Blog.github.io/main/img/bac-14.jpg">点击开启星辰之旅</a></div></div></div><div class="t-t-r"><p class="ft-t t-l-t">猜你想看💡</p><ul class="ft-links"><li><a target="_blank" rel="noopener" href="https://www.fomal.cc/posts/eec9786.html">魔改指南</a><a href="/comments/">留点什么</a></li><li><a href="/link/">我的朋友</a><a href="/Gallery/">我的照片</a></li><li><a href="/game/">我的游戏</a><a href="/music/">我的音乐</a></li><li><a href="/categories/">文章分类</a><a href="/tags/">文章标签</a></li><li><a href="/about/">关于作者</a><a target="_blank" rel="noopener" href="https://www.fomal.cc/posts/e593433d.html">网址导航</a></li></ul></div></div></div><div class="ft-item-2"><p class="ft-t">推荐友链⌛</p><div class="ft-img-group"><div class="img-group-item"><a href="/img/wechat.jpg" title="SRS🥝"><img src= "" data-lazy-src="/img/srs.jpg" alt=""/></a></div><div class="img-group-item"><a href="/img/xxwechat.jpg" title="潇潇🥝"><img src= "" data-lazy-src="/img/wyx.jpg" alt=""/></a></div></div></div></div><div class="copyright"><span><b>&copy;2025</b></span><span><b>&nbsp;&nbsp;By SRS</b></span></div><div id="workboard"><link rel="stylesheet" href="/css/runtime.css"/><script src="/js/runtime.js"></script></div><p id="ghbdages"><!-- SRS-Blog 徽标--><a class="github-badge" target="_blank" href="https://github.com/SRS-Blog" style="margin-inline:5px" title="SRS-Blog"><img src= "" data-lazy-src="https://img.shields.io/badge/SRS-Me-red" alt="SRS-Blog"/></a><!-- Hexo 徽标--><a class="github-badge" target="_blank" href="https://hexo.io/" style="margin-inline:5px" title="博客框架为Hexo"><img src= "" data-lazy-src="https://img.shields.io/badge/Frame-Hexo-blue?style=flat&amp;logo=hexo" alt="Hexo"/></a><!-- Butterfly 徽标--><a class="github-badge" target="_blank" href="https://butterfly.js.org/" style="margin-inline:5px" title="主题Butterfly"><img src= "" data-lazy-src="https://img.shields.io/badge/Theme-Butterfly-6513df?style=flat&amp;logo=bitdefender" alt="Butterfly"/></a><!-- Netlify 徽标--><a class="github-badge" target="_blank" href="https://app.netlify.com/" style="margin-inline:5px" title="Netlify部署"><img src= "" data-lazy-src="https://img.shields.io/badge/Deploy-Netlify-green" alt="Netlify"/></a><!-- Github 托管徽标--><a class="github-badge" target="_blank" href="https://github.com/" style="margin-inline:5px" title="本站项目由Github托管"><img src= "" data-lazy-src="https://img.shields.io/badge/Source-Github-d021d6?style=flat&amp;logo=GitHub" alt="Github"/></a><!-- CC 协议徽标--><a class="github-badge" target="_blank" href="http://creativecommons.org/licenses/by-nc-sa/4.0/" style="margin-inline:5px" title="本站采用知识共享署名-非商业性使用"><img src= "" data-lazy-src="https://img.shields.io/badge/Copyright-BY--NC--SA%204.0-d42328?style=flat&amp;logo=Claris" alt="CC BY-NC-SA 4.0"/></a></p></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="translateLink" type="button" title="简繁转换">繁</button><button id="darkmode" type="button" title="日间和夜间模式切换"><i class="fas fa-adjust"></i></button></div><div id="rightside-config-show"><button id="rightside-config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="share" type="button" title="分享链接" onclick="share()"><i class="fas fa-share-nodes"></i></button><a id="to_comment" href="#post-comment" title="前往评论"><i class="fas fa-comments"></i></a><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><button id="go-up" type="button" title="回到顶部"><i class="fas fa-arrow-up"></i><span id="percent">0<span>%</span></span></button><button id="go-down" type="button" title="直达底部" onclick="btf.scrollToDest(document.body.scrollHeight, 500)"><i class="fas fa-arrow-down"></i></button></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="/js/tw_cn.js"></script><script src="https://cdn.jsdelivr.net/npm/instant.page/instantpage.min.js" type="module"></script><script src="https://cdn.jsdelivr.net/npm/vanilla-lazyload/dist/lazyload.iife.min.js"></script><script src="https://cdn.jsdelivr.net/npm/node-snackbar/dist/snackbar.min.js"></script><div class="js-pjax"><script>(() => {
  const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo'
  const option = null

  const getCount = () => {
    const countELement = document.getElementById('twikoo-count')
    if(!countELement) return
    twikoo.getCommentsCount({
      envId: 'https://ubiquitous-panda-07c371.netlify.app/.netlify/functions/twikoo',
      region: '',
      urls: [window.location.pathname],
      includeReply: false
    }).then(res => {
      countELement.textContent = res[0].count
    }).catch(err => {
      console.error(err)
    })
  }

  const init = (el = document, path = location.pathname) => {
    twikoo.init({
      el: el.querySelector('#twikoo-wrap'),
      envId: 'https://ubiquitous-panda-07c371.netlify.app/.netlify/functions/twikoo',
      region: '',
      onCommentLoaded: () => {
        btf.loadLightbox(document.querySelectorAll('#twikoo .tk-content img:not(.tk-owo-emotion)'))
      },
      ...option,
      path: isShuoshuo ? path : (option && option.path) || path
    })

    

    isShuoshuo && (window.shuoshuoComment.destroyTwikoo = () => {
      if (el.children.length) {
        el.innerHTML = ''
        el.classList.add('no-comment')
      }
    })
  }

  const loadTwikoo = (el, path) => {
    if (typeof twikoo === 'object') setTimeout(() => init(el, path), 0)
    else btf.getScript('https://cdn.jsdelivr.net/npm/twikoo/dist/twikoo.all.min.js').then(() => init(el, path))
  }

  if (isShuoshuo) {
    'Twikoo' === 'Twikoo'
      ? window.shuoshuoComment = { loadComment: loadTwikoo }
      : window.loadOtherComment = loadTwikoo
    return
  }

  if ('Twikoo' === 'Twikoo' || !true) {
    if (true) btf.loadComment(document.getElementById('twikoo-wrap'), loadTwikoo)
    else loadTwikoo()
  } else {
    window.loadOtherComment = loadTwikoo
  }
})()</script></div><script async data-pjax src="/js/txmap.js"></script><script src="https://npm.elemecdn.com/jquery@latest/dist/jquery.min.js"></script><script defer src="/js/light.js"></script><canvas id="universe"></canvas><script defer src="/js/universe.js"></script><script defer src="/js/cursor.js"></script><script defer src="/js/emoji.js"></script><script async src="//npm.elemecdn.com/pace-js@1.2.4/pace.min.js"></script><div class="aplayer no-destroy" data-id="9472457949" data-server="tencent" data-type="playlist" data-fixed="true" data-autoplay="true"> </div><script async src="//at.alicdn.com/t/c/font_4887470_r6tyhzjqh8q.js"></script><script src="/js/nav.js"></script><script defer data-pjax src="/js/readPercent.js"></script><script async src="https://npm.elemecdn.com/tzy-blog/lib/js/other/sakura.js"></script><script async src="/js/title.js"></script><script async src="https://cdn1.tianli0.top/npm/vue@2.6.14/dist/vue.min.js"></script><script async src="https://cdn1.tianli0.top/npm/element-ui@2.15.6/lib/index.js"></script><script src="https://cdn.bootcdn.net/ajax/libs/clipboard.js/2.0.11/clipboard.min.js"></script><script src="/js/share.js"></script><script id="canvas_nest" defer="defer" color="0,0,255" opacity="0.7" zIndex="-1" count="30" mobile="false" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/dist/canvas-nest.min.js"></script><script id="click-heart" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/dist/click-heart.min.js" async="async" mobile="true"></script><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/metingjs/dist/Meting.min.js"></script><script>(() => {
  const destroyAplayer = () => {
    if (window.aplayers) {
      for (let i = 0; i < window.aplayers.length; i++) {
        if (!window.aplayers[i].options.fixed) {
          window.aplayers[i].destroy()
        }
      }
    }
  }

  const runMetingJS = () => {
    typeof loadMeting === 'function' && document.getElementsByClassName('aplayer').length && loadMeting()
  }

  btf.addGlobalFn('pjaxSend', destroyAplayer, 'destroyAplayer')
  btf.addGlobalFn('pjaxComplete', loadMeting, 'runMetingJS')
})()</script><script src="https://cdn.jsdelivr.net/npm/pjax/pjax.min.js"></script><script>(() => {
  const pjaxSelectors = ["head > title","#config-diff","#body-wrap","#rightside-config-hide","#rightside-config-show",".js-pjax"]

  window.pjax = new Pjax({
    elements: 'a:not([target="_blank"])',
    selectors: pjaxSelectors,
    cacheBust: false,
    analytics: false,
    scrollRestoration: false
  })

  const triggerPjaxFn = (val) => {
    if (!val) return
    Object.values(val).forEach(fn => fn())
  }

  document.addEventListener('pjax:send', () => {
    // removeEventListener
    btf.removeGlobalFnEvent('pjaxSendOnce')
    btf.removeGlobalFnEvent('themeChange')

    // reset readmode
    const $bodyClassList = document.body.classList
    if ($bodyClassList.contains('read-mode')) $bodyClassList.remove('read-mode')

    triggerPjaxFn(window.globalFn.pjaxSend)
  })

  document.addEventListener('pjax:complete', () => {
    btf.removeGlobalFnEvent('pjaxCompleteOnce')
    document.querySelectorAll('script[data-pjax]').forEach(item => {
      const newScript = document.createElement('script')
      const content = item.text || item.textContent || item.innerHTML || ""
      Array.from(item.attributes).forEach(attr => newScript.setAttribute(attr.name, attr.value))
      newScript.appendChild(document.createTextNode(content))
      item.parentNode.replaceChild(newScript, item)
    })

    triggerPjaxFn(window.globalFn.pjaxComplete)
  })

  document.addEventListener('pjax:error', e => {
    if (e.request.status === 404) {
      const usePjax = true
      true 
        ? (usePjax ? pjax.loadUrl('/404.html') : window.location.href = '/404.html')
        : window.location.href = e.request.responseURL
    }
  })
})()</script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><div id="local-search"><div class="search-dialog"><nav class="search-nav"><span class="search-dialog-title">搜索</span><span id="loading-status"></span><button class="search-close-button"><i class="fas fa-times"></i></button></nav><div class="text-center" id="loading-database"><i class="fas fa-spinner fa-pulse"></i><span>  数据加载中</span></div><div class="search-wrap"><div id="local-search-input"><div class="local-search-box"><input class="local-search-box--input" placeholder="搜索文章" type="text"/></div></div><hr/><div id="local-search-results"></div><div id="local-search-stats-wrap"></div></div></div><div id="search-mask"></div><script src="/js/search/local-search.js"></script></div></div><!-- hexo injector body_end start --> <script data-pjax>if(document.getElementById('recent-posts') && (location.pathname ==='/'|| '/' ==='all')){
    var parent = document.getElementById('recent-posts');
    var child = '<div class="recent-post-item" style="width:100%;height: auto"><div id="catalog_magnet"><div class="magnet_item"><a class="magnet_link" href="https://srs-blog.github.io/categories/PYTHON/"><div class="magnet_link_context" style=""><span style="font-weight:500;flex:1">📚 PYTHON (1)</span><span style="padding:0px 4px;border-radius: 8px;"><i class="fas fa-arrow-circle-right"></i></span></div></a></div><div class="magnet_item"><a class="magnet_link" href="https://srs-blog.github.io/categories/C/"><div class="magnet_link_context" style=""><span style="font-weight:500;flex:1">🎮 C++ (1)</span><span style="padding:0px 4px;border-radius: 8px;"><i class="fas fa-arrow-circle-right"></i></span></div></a></div><div class="magnet_item"><a class="magnet_link" href="https://srs-blog.github.io/categories/Hexo/"><div class="magnet_link_context" style=""><span style="font-weight:500;flex:1">🐱‍👓 Hexo (1)</span><span style="padding:0px 4px;border-radius: 8px;"><i class="fas fa-arrow-circle-right"></i></span></div></a></div><div class="magnet_item"><a class="magnet_link" href="https://srs-blog.github.io/categories/Java/"><div class="magnet_link_context" style=""><span style="font-weight:500;flex:1">👩‍💻 Java (6)</span><span style="padding:0px 4px;border-radius: 8px;"><i class="fas fa-arrow-circle-right"></i></span></div></a></div><a class="magnet_link_more"  href="https://srs-blog.github.io/categories" style="flex:1;text-align: center;margin-bottom: 10px;">查看更多...</a></div></div>';
    console.log('已挂载magnet')
    parent.insertAdjacentHTML("afterbegin",child)}
     </script><style>#catalog_magnet{flex-wrap: wrap;display: flex;width:100%;justify-content:space-between;padding: 10px 10px 0 10px;align-content: flex-start;}.magnet_item{flex-basis: calc(50% - 5px);background: #f2f2f2;margin-bottom: 10px;border-radius: 8px;transition: all 0.2s ease-in-out;}.magnet_item:hover{background: #b30070}.magnet_link_more{color:#555}.magnet_link{color:black}.magnet_link:hover{color:white}@media screen and (max-width: 600px) {.magnet_item {flex-basis: 100%;}}.magnet_link_context{display:flex;padding: 10px;font-size:16px;transition: all 0.2s ease-in-out;}.magnet_link_context:hover{padding: 10px 20px;}</style>
    <style></style><script data-pjax>
  function butterfly_swiper_injector_config(){
    var parent_div_git = document.getElementById('recent-posts');
    var item_html = '<div class="recent-post-item" style="height: auto;width: 100%"><div class="blog-slider swiper-container-fade swiper-container-horizontal" id="swiper_container"><div class="blog-slider__wrp swiper-wrapper" style="transition-duration: 0ms;"><div class="blog-slider__item swiper-slide" style="width: 750px; opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><a class="blog-slider__img" onclick="pjax.loadUrl(&quot;2025/04/08/2025-4-8-第一篇文章/&quot;);" href="javascript:void(0);" alt=""><img width="48" height="48" src= "" data-lazy-src="/img/bac-13.jpg" alt="" onerror="this.src=https://unpkg.zhimg.com/akilar-candyassets/image/loading.gif; this.onerror = null;"/></a><div class="blog-slider__content"><span class="blog-slider__code">2025-04-08</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;2025/04/08/2025-4-8-第一篇文章/&quot;);" href="javascript:void(0);" alt="">第一篇文章</a><div class="blog-slider__text">再怎么看我也不知道怎么描述它的啦！</div><a class="blog-slider__button" onclick="pjax.loadUrl(&quot;2025/04/08/2025-4-8-第一篇文章/&quot;);" href="javascript:void(0);" alt="">详情       </a></div></div><div class="blog-slider__item swiper-slide" style="width: 750px; opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><a class="blog-slider__img" onclick="pjax.loadUrl(&quot;2025/04/08/2025-4-8-第二篇文章/&quot;);" href="javascript:void(0);" alt=""><img width="48" height="48" src= "" data-lazy-src="/img/bac-9.jpg" alt="" onerror="this.src=https://unpkg.zhimg.com/akilar-candyassets/image/loading.gif; this.onerror = null;"/></a><div class="blog-slider__content"><span class="blog-slider__code">2025-04-08</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;2025/04/08/2025-4-8-第二篇文章/&quot;);" href="javascript:void(0);" alt="">第二篇文章</a><div class="blog-slider__text">再怎么看我也不知道怎么描述它的啦！</div><a class="blog-slider__button" onclick="pjax.loadUrl(&quot;2025/04/08/2025-4-8-第二篇文章/&quot;);" href="javascript:void(0);" alt="">详情       </a></div></div><div class="blog-slider__item swiper-slide" style="width: 750px; opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><a class="blog-slider__img" onclick="pjax.loadUrl(&quot;2025/04/08/2025-4-8-第三篇文章/&quot;);" href="javascript:void(0);" alt=""><img width="48" height="48" src= "" data-lazy-src="/img/bac-15.jpg" alt="" onerror="this.src=https://unpkg.zhimg.com/akilar-candyassets/image/loading.gif; this.onerror = null;"/></a><div class="blog-slider__content"><span class="blog-slider__code">2025-04-08</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;2025/04/08/2025-4-8-第三篇文章/&quot;);" href="javascript:void(0);" alt="">第三篇文章</a><div class="blog-slider__text">再怎么看我也不知道怎么描述它的啦！</div><a class="blog-slider__button" onclick="pjax.loadUrl(&quot;2025/04/08/2025-4-8-第三篇文章/&quot;);" href="javascript:void(0);" alt="">详情       </a></div></div><div class="blog-slider__item swiper-slide" style="width: 750px; opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><a class="blog-slider__img" onclick="pjax.loadUrl(&quot;2025/04/13/若依基础应用篇/&quot;);" href="javascript:void(0);" alt=""><img width="48" height="48" src= "" data-lazy-src="/img/bac-1.jpg" alt="" onerror="this.src=https://unpkg.zhimg.com/akilar-candyassets/image/loading.gif; this.onerror = null;"/></a><div class="blog-slider__content"><span class="blog-slider__code">2025-04-13</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;2025/04/13/若依基础应用篇/&quot;);" href="javascript:void(0);" alt="">若依框架</a><div class="blog-slider__text">再怎么看我也不知道怎么描述它的啦！</div><a class="blog-slider__button" onclick="pjax.loadUrl(&quot;2025/04/13/若依基础应用篇/&quot;);" href="javascript:void(0);" alt="">详情       </a></div></div><div class="blog-slider__item swiper-slide" style="width: 750px; opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><a class="blog-slider__img" onclick="pjax.loadUrl(&quot;2025/04/11/多线程/&quot;);" href="javascript:void(0);" alt=""><img width="48" height="48" src= "" data-lazy-src="/img/bac-7.jpg" alt="" onerror="this.src=https://unpkg.zhimg.com/akilar-candyassets/image/loading.gif; this.onerror = null;"/></a><div class="blog-slider__content"><span class="blog-slider__code">2025-04-11</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;2025/04/11/多线程/&quot;);" href="javascript:void(0);" alt="">多线程</a><div class="blog-slider__text">再怎么看我也不知道怎么描述它的啦！</div><a class="blog-slider__button" onclick="pjax.loadUrl(&quot;2025/04/11/多线程/&quot;);" href="javascript:void(0);" alt="">详情       </a></div></div><div class="blog-slider__item swiper-slide" style="width: 750px; opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><a class="blog-slider__img" onclick="pjax.loadUrl(&quot;2025/04/11/JUC/&quot;);" href="javascript:void(0);" alt=""><img width="48" height="48" src= "" data-lazy-src="/img/bac-4.jpg" alt="" onerror="this.src=https://unpkg.zhimg.com/akilar-candyassets/image/loading.gif; this.onerror = null;"/></a><div class="blog-slider__content"><span class="blog-slider__code">2025-04-11</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;2025/04/11/JUC/&quot;);" href="javascript:void(0);" alt="">JUC</a><div class="blog-slider__text">再怎么看我也不知道怎么描述它的啦！</div><a class="blog-slider__button" onclick="pjax.loadUrl(&quot;2025/04/11/JUC/&quot;);" href="javascript:void(0);" alt="">详情       </a></div></div><div class="blog-slider__item swiper-slide" style="width: 750px; opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><a class="blog-slider__img" onclick="pjax.loadUrl(&quot;2025/04/10/IO-异常-File-综合案例/&quot;);" href="javascript:void(0);" alt=""><img width="48" height="48" src= "" data-lazy-src="/img/bac-12.jpg" alt="" onerror="this.src=https://unpkg.zhimg.com/akilar-candyassets/image/loading.gif; this.onerror = null;"/></a><div class="blog-slider__content"><span class="blog-slider__code">2025-04-10</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;2025/04/10/IO-异常-File-综合案例/&quot;);" href="javascript:void(0);" alt="">异常&amp;File</a><div class="blog-slider__text">再怎么看我也不知道怎么描述它的啦！</div><a class="blog-slider__button" onclick="pjax.loadUrl(&quot;2025/04/10/IO-异常-File-综合案例/&quot;);" href="javascript:void(0);" alt="">详情       </a></div></div><div class="blog-slider__item swiper-slide" style="width: 750px; opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><a class="blog-slider__img" onclick="pjax.loadUrl(&quot;2025/04/10/IO流-字节流-字符流/&quot;);" href="javascript:void(0);" alt=""><img width="48" height="48" src= "" data-lazy-src="/img/bac-15.jpg" alt="" onerror="this.src=https://unpkg.zhimg.com/akilar-candyassets/image/loading.gif; this.onerror = null;"/></a><div class="blog-slider__content"><span class="blog-slider__code">2025-04-10</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;2025/04/10/IO流-字节流-字符流/&quot;);" href="javascript:void(0);" alt="">IO流</a><div class="blog-slider__text">再怎么看我也不知道怎么描述它的啦！</div><a class="blog-slider__button" onclick="pjax.loadUrl(&quot;2025/04/10/IO流-字节流-字符流/&quot;);" href="javascript:void(0);" alt="">详情       </a></div></div><div class="blog-slider__item swiper-slide" style="width: 750px; opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><a class="blog-slider__img" onclick="pjax.loadUrl(&quot;2025/04/10/IO流-其他流/&quot;);" href="javascript:void(0);" alt=""><img width="48" height="48" src= "" data-lazy-src="/img/bac-13.jpg" alt="" onerror="this.src=https://unpkg.zhimg.com/akilar-candyassets/image/loading.gif; this.onerror = null;"/></a><div class="blog-slider__content"><span class="blog-slider__code">2025-04-10</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;2025/04/10/IO流-其他流/&quot;);" href="javascript:void(0);" alt="">IO流--扩展流</a><div class="blog-slider__text">再怎么看我也不知道怎么描述它的啦！</div><a class="blog-slider__button" onclick="pjax.loadUrl(&quot;2025/04/10/IO流-其他流/&quot;);" href="javascript:void(0);" alt="">详情       </a></div></div></div><div class="blog-slider__pagination swiper-pagination-clickable swiper-pagination-bullets"></div></div></div>';
    console.log('已挂载butterfly_swiper')
    parent_div_git.insertAdjacentHTML("afterbegin",item_html)
    }
  var elist = 'undefined'.split(',');
  var cpage = location.pathname;
  var epage = '/';
  var flag = 0;

  for (var i=0;i<elist.length;i++){
    if (cpage.includes(elist[i])){
      flag++;
    }
  }

  if ((epage ==='all')&&(flag == 0)){
    butterfly_swiper_injector_config();
  }
  else if (epage === cpage){
    butterfly_swiper_injector_config();
  }
  </script><script defer src="https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper.min.js"></script><script defer data-pjax src="https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper_init.js"></script><div class="js-pjax"><script async="async">var arr = document.getElementsByClassName('recent-post-item');
for(var i = 0;i<arr.length;i++){
    arr[i].classList.add('wow');
    arr[i].classList.add('animate__zoomIn');
    arr[i].setAttribute('data-wow-duration', '2s');
    arr[i].setAttribute('data-wow-delay', '1s');
    arr[i].setAttribute('data-wow-offset', '100');
    arr[i].setAttribute('data-wow-iteration', '2');
  }</script><script async="async">var arr = document.getElementsByClassName('card-widget');
for(var i = 0;i<arr.length;i++){
    arr[i].classList.add('wow');
    arr[i].classList.add('animate__zoomIn');
    arr[i].setAttribute('data-wow-duration', '');
    arr[i].setAttribute('data-wow-delay', '');
    arr[i].setAttribute('data-wow-offset', '');
    arr[i].setAttribute('data-wow-iteration', '');
  }</script></div><script defer src="https://npm.elemecdn.com/hexo-butterfly-wowjs/lib/wow.min.js"></script><script defer src="https://npm.elemecdn.com/hexo-butterfly-wowjs/lib/wow_init.js"></script><script async src="//at.alicdn.com/t/font_2032782_8d5kxvn09md.js"></script><!-- hexo injector body_end end --><script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","tagMode":false,"debug":false,"model":{"jsonPath":"/live2dw/assets/haruto.model.json"},"display":{"position":"right","width":160,"height":260},"mobile":{"show":true},"log":false});</script></body></html>